These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * List tables: orders. |
||
4 | * |
||
5 | * @package WooCommerce\admin |
||
6 | * @version 3.3.0 |
||
7 | */ |
||
8 | |||
9 | if ( ! defined( 'ABSPATH' ) ) { |
||
10 | exit; |
||
11 | } |
||
12 | |||
13 | if ( class_exists( 'WC_Admin_List_Table_Orders', false ) ) { |
||
14 | return; |
||
15 | } |
||
16 | |||
17 | if ( ! class_exists( 'WC_Admin_List_Table', false ) ) { |
||
18 | include_once 'abstract-class-wc-admin-list-table.php'; |
||
19 | } |
||
20 | |||
21 | /** |
||
22 | * WC_Admin_List_Table_Orders Class. |
||
23 | */ |
||
24 | class WC_Admin_List_Table_Orders extends WC_Admin_List_Table { |
||
25 | |||
26 | /** |
||
27 | * Post type. |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | protected $list_table_type = 'shop_order'; |
||
32 | |||
33 | /** |
||
34 | * Constructor. |
||
35 | */ |
||
36 | public function __construct() { |
||
37 | parent::__construct(); |
||
38 | add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) ); |
||
39 | add_action( 'admin_footer', array( $this, 'order_preview_template' ) ); |
||
40 | add_filter( 'get_search_query', array( $this, 'search_label' ) ); |
||
41 | add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) ); |
||
42 | add_action( 'parse_query', array( $this, 'search_custom_fields' ) ); |
||
43 | } |
||
44 | |||
45 | /** |
||
46 | * Render blank state. |
||
47 | */ |
||
48 | protected function render_blank_state() { |
||
49 | echo '<div class="woocommerce-BlankState">'; |
||
50 | |||
51 | echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'When you receive a new order, it will appear here.', 'woocommerce' ) . '</h2>'; |
||
52 | |||
53 | echo '<div class="woocommerce-BlankState-buttons">'; |
||
54 | echo '<a class="woocommerce-BlankState-cta button-primary button" target="_blank" href="https://docs.woocommerce.com/document/managing-orders/?utm_source=blankslate&utm_medium=product&utm_content=ordersdoc&utm_campaign=woocommerceplugin">' . esc_html__( 'Learn more about orders', 'woocommerce' ) . '</a>'; |
||
55 | echo '</div>'; |
||
56 | |||
57 | do_action( 'wc_marketplace_suggestions_orders_empty_state' ); |
||
58 | |||
59 | echo '</div>'; |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * Define primary column. |
||
64 | * |
||
65 | * @return string |
||
66 | */ |
||
67 | protected function get_primary_column() { |
||
68 | return 'order_number'; |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * Get row actions to show in the list table. |
||
73 | * |
||
74 | * @param array $actions Array of actions. |
||
75 | * @param WP_Post $post Current post object. |
||
76 | * @return array |
||
77 | */ |
||
78 | protected function get_row_actions( $actions, $post ) { |
||
79 | return array(); |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * Define hidden columns. |
||
84 | * |
||
85 | * @return array |
||
86 | */ |
||
87 | protected function define_hidden_columns() { |
||
88 | return array( |
||
89 | 'shipping_address', |
||
90 | 'billing_address', |
||
91 | 'wc_actions', |
||
92 | ); |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * Define which columns are sortable. |
||
97 | * |
||
98 | * @param array $columns Existing columns. |
||
99 | * @return array |
||
100 | */ |
||
101 | public function define_sortable_columns( $columns ) { |
||
102 | $custom = array( |
||
103 | 'order_number' => 'ID', |
||
104 | 'order_total' => 'order_total', |
||
105 | 'order_date' => 'date', |
||
106 | ); |
||
107 | unset( $columns['comments'] ); |
||
108 | |||
109 | return wp_parse_args( $custom, $columns ); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * Define which columns to show on this screen. |
||
114 | * |
||
115 | * @param array $columns Existing columns. |
||
116 | * @return array |
||
117 | */ |
||
118 | public function define_columns( $columns ) { |
||
119 | $show_columns = array(); |
||
120 | $show_columns['cb'] = $columns['cb']; |
||
121 | $show_columns['order_number'] = __( 'Order', 'woocommerce' ); |
||
122 | $show_columns['order_date'] = __( 'Date', 'woocommerce' ); |
||
123 | $show_columns['order_status'] = __( 'Status', 'woocommerce' ); |
||
124 | $show_columns['billing_address'] = __( 'Billing', 'woocommerce' ); |
||
125 | $show_columns['shipping_address'] = __( 'Ship to', 'woocommerce' ); |
||
126 | $show_columns['order_total'] = __( 'Total', 'woocommerce' ); |
||
127 | $show_columns['wc_actions'] = __( 'Actions', 'woocommerce' ); |
||
128 | |||
129 | wp_enqueue_script( 'wc-orders' ); |
||
130 | |||
131 | return $show_columns; |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Define bulk actions. |
||
136 | * |
||
137 | * @param array $actions Existing actions. |
||
138 | * @return array |
||
139 | */ |
||
140 | public function define_bulk_actions( $actions ) { |
||
141 | if ( isset( $actions['edit'] ) ) { |
||
142 | unset( $actions['edit'] ); |
||
143 | } |
||
144 | |||
145 | $actions['mark_processing'] = __( 'Change status to processing', 'woocommerce' ); |
||
146 | $actions['mark_on-hold'] = __( 'Change status to on-hold', 'woocommerce' ); |
||
147 | $actions['mark_completed'] = __( 'Change status to completed', 'woocommerce' ); |
||
148 | |||
149 | if ( wc_string_to_bool( get_option( 'woocommerce_allow_bulk_remove_personal_data', 'no' ) ) ) { |
||
150 | $actions['remove_personal_data'] = __( 'Remove personal data', 'woocommerce' ); |
||
151 | } |
||
152 | |||
153 | return $actions; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Pre-fetch any data for the row each column has access to it. the_order global is there for bw compat. |
||
158 | * |
||
159 | * @param int $post_id Post ID being shown. |
||
160 | */ |
||
161 | View Code Duplication | protected function prepare_row_data( $post_id ) { |
|
162 | global $the_order; |
||
163 | |||
164 | if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) { |
||
165 | $this->object = wc_get_order( $post_id ); |
||
166 | $the_order = $this->object; |
||
167 | } |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * Render columm: order_number. |
||
172 | */ |
||
173 | protected function render_order_number_column() { |
||
174 | $buyer = ''; |
||
175 | |||
176 | if ( $this->object->get_billing_first_name() || $this->object->get_billing_last_name() ) { |
||
177 | /* translators: 1: first name 2: last name */ |
||
178 | $buyer = trim( sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->object->get_billing_first_name(), $this->object->get_billing_last_name() ) ); |
||
179 | } elseif ( $this->object->get_billing_company() ) { |
||
180 | $buyer = trim( $this->object->get_billing_company() ); |
||
181 | } elseif ( $this->object->get_customer_id() ) { |
||
182 | $user = get_user_by( 'id', $this->object->get_customer_id() ); |
||
183 | $buyer = ucwords( $user->display_name ); |
||
184 | } |
||
185 | |||
186 | if ( $this->object->get_status() === 'trash' ) { |
||
187 | echo '<strong>#' . esc_attr( $this->object->get_order_number() ) . ' ' . esc_html( $buyer ) . '</strong>'; |
||
188 | } else { |
||
189 | echo '<a href="#" class="order-preview" data-order-id="' . absint( $this->object->get_id() ) . '" title="' . esc_attr( __( 'Preview', 'woocommerce' ) ) . '">' . esc_html( __( 'Preview', 'woocommerce' ) ) . '</a>'; |
||
190 | echo '<a href="' . esc_url( admin_url( 'post.php?post=' . absint( $this->object->get_id() ) ) . '&action=edit' ) . '" class="order-view"><strong>#' . esc_attr( $this->object->get_order_number() ) . ' ' . esc_html( $buyer ) . '</strong></a>'; |
||
191 | } |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Render columm: order_status. |
||
196 | */ |
||
197 | protected function render_order_status_column() { |
||
198 | $tooltip = ''; |
||
199 | $comment_count = get_comment_count( $this->object->get_id() ); |
||
200 | $approved_comments_count = absint( $comment_count['approved'] ); |
||
201 | |||
202 | if ( $approved_comments_count ) { |
||
203 | $latest_notes = wc_get_order_notes( |
||
204 | array( |
||
205 | 'order_id' => $this->object->get_id(), |
||
206 | 'limit' => 1, |
||
207 | 'orderby' => 'date_created_gmt', |
||
208 | ) |
||
209 | ); |
||
210 | |||
211 | $latest_note = current( $latest_notes ); |
||
212 | |||
213 | if ( isset( $latest_note->content ) && 1 === $approved_comments_count ) { |
||
214 | $tooltip = wc_sanitize_tooltip( $latest_note->content ); |
||
215 | } elseif ( isset( $latest_note->content ) ) { |
||
216 | /* translators: %d: notes count */ |
||
217 | $tooltip = wc_sanitize_tooltip( $latest_note->content . '<br/><small style="display:block">' . sprintf( _n( 'Plus %d other note', 'Plus %d other notes', ( $approved_comments_count - 1 ), 'woocommerce' ), $approved_comments_count - 1 ) . '</small>' ); |
||
218 | } else { |
||
219 | /* translators: %d: notes count */ |
||
220 | $tooltip = wc_sanitize_tooltip( sprintf( _n( '%d note', '%d notes', $approved_comments_count, 'woocommerce' ), $approved_comments_count ) ); |
||
221 | } |
||
222 | } |
||
223 | |||
224 | if ( $tooltip ) { |
||
225 | printf( '<mark class="order-status %s tips" data-tip="%s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), wp_kses_post( $tooltip ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) ); |
||
226 | } else { |
||
227 | printf( '<mark class="order-status %s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) ); |
||
228 | } |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * Render columm: order_date. |
||
233 | */ |
||
234 | protected function render_order_date_column() { |
||
235 | $order_timestamp = $this->object->get_date_created() ? $this->object->get_date_created()->getTimestamp() : ''; |
||
236 | |||
237 | if ( ! $order_timestamp ) { |
||
238 | echo '–'; |
||
239 | return; |
||
240 | } |
||
241 | |||
242 | // Check if the order was created within the last 24 hours, and not in the future. |
||
243 | if ( $order_timestamp > strtotime( '-1 day', current_time( 'timestamp', true ) ) && $order_timestamp <= current_time( 'timestamp', true ) ) { |
||
244 | $show_date = sprintf( |
||
245 | /* translators: %s: human-readable time difference */ |
||
246 | _x( '%s ago', '%s = human-readable time difference', 'woocommerce' ), |
||
247 | human_time_diff( $this->object->get_date_created()->getTimestamp(), current_time( 'timestamp', true ) ) |
||
248 | ); |
||
249 | } else { |
||
250 | $show_date = $this->object->get_date_created()->date_i18n( apply_filters( 'woocommerce_admin_order_date_format', __( 'M j, Y', 'woocommerce' ) ) ); |
||
251 | } |
||
252 | printf( |
||
253 | '<time datetime="%1$s" title="%2$s">%3$s</time>', |
||
254 | esc_attr( $this->object->get_date_created()->date( 'c' ) ), |
||
255 | esc_html( $this->object->get_date_created()->date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) ), |
||
256 | esc_html( $show_date ) |
||
257 | ); |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Render columm: order_total. |
||
262 | */ |
||
263 | protected function render_order_total_column() { |
||
264 | if ( $this->object->get_payment_method_title() ) { |
||
265 | /* translators: %s: method */ |
||
266 | echo '<span class="tips" data-tip="' . esc_attr( sprintf( __( 'via %s', 'woocommerce' ), $this->object->get_payment_method_title() ) ) . '">' . wp_kses_post( $this->object->get_formatted_order_total() ) . '</span>'; |
||
267 | } else { |
||
268 | echo wp_kses_post( $this->object->get_formatted_order_total() ); |
||
269 | } |
||
270 | } |
||
271 | |||
272 | /** |
||
273 | * Render columm: wc_actions. |
||
274 | */ |
||
275 | protected function render_wc_actions_column() { |
||
276 | echo '<p>'; |
||
277 | |||
278 | do_action( 'woocommerce_admin_order_actions_start', $this->object ); |
||
279 | |||
280 | $actions = array(); |
||
281 | |||
282 | View Code Duplication | if ( $this->object->has_status( array( 'pending', 'on-hold' ) ) ) { |
|
283 | $actions['processing'] = array( |
||
284 | 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $this->object->get_id() ), 'woocommerce-mark-order-status' ), |
||
285 | 'name' => __( 'Processing', 'woocommerce' ), |
||
286 | 'action' => 'processing', |
||
287 | ); |
||
288 | } |
||
289 | |||
290 | View Code Duplication | if ( $this->object->has_status( array( 'pending', 'on-hold', 'processing' ) ) ) { |
|
291 | $actions['complete'] = array( |
||
292 | 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $this->object->get_id() ), 'woocommerce-mark-order-status' ), |
||
293 | 'name' => __( 'Complete', 'woocommerce' ), |
||
294 | 'action' => 'complete', |
||
295 | ); |
||
296 | } |
||
297 | |||
298 | $actions = apply_filters( 'woocommerce_admin_order_actions', $actions, $this->object ); |
||
299 | |||
300 | echo wc_render_action_buttons( $actions ); // WPCS: XSS ok. |
||
301 | |||
302 | do_action( 'woocommerce_admin_order_actions_end', $this->object ); |
||
303 | |||
304 | echo '</p>'; |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * Render columm: billing_address. |
||
309 | */ |
||
310 | protected function render_billing_address_column() { |
||
311 | $address = $this->object->get_formatted_billing_address(); |
||
312 | |||
313 | if ( $address ) { |
||
314 | echo esc_html( preg_replace( '#<br\s*/?>#i', ', ', $address ) ); |
||
315 | |||
316 | if ( $this->object->get_payment_method() ) { |
||
317 | /* translators: %s: payment method */ |
||
318 | echo '<span class="description">' . sprintf( __( 'via %s', 'woocommerce' ), esc_html( $this->object->get_payment_method_title() ) ) . '</span>'; // WPCS: XSS ok. |
||
319 | } |
||
320 | } else { |
||
321 | echo '–'; |
||
322 | } |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Render columm: shipping_address. |
||
327 | */ |
||
328 | protected function render_shipping_address_column() { |
||
329 | $address = $this->object->get_formatted_shipping_address(); |
||
330 | |||
331 | if ( $address ) { |
||
332 | echo '<a target="_blank" href="' . esc_url( $this->object->get_shipping_address_map_url() ) . '">' . esc_html( preg_replace( '#<br\s*/?>#i', ', ', $address ) ) . '</a>'; |
||
333 | if ( $this->object->get_shipping_method() ) { |
||
334 | /* translators: %s: shipping method */ |
||
335 | echo '<span class="description">' . sprintf( __( 'via %s', 'woocommerce' ), esc_html( $this->object->get_shipping_method() ) ) . '</span>'; // WPCS: XSS ok. |
||
336 | } |
||
337 | } else { |
||
338 | echo '–'; |
||
339 | } |
||
340 | } |
||
341 | |||
342 | /** |
||
343 | * Template for order preview. |
||
344 | * |
||
345 | * @since 3.3.0 |
||
346 | */ |
||
347 | public function order_preview_template() { |
||
348 | ?> |
||
349 | <script type="text/template" id="tmpl-wc-modal-view-order"> |
||
350 | <div class="wc-backbone-modal wc-order-preview"> |
||
351 | <div class="wc-backbone-modal-content"> |
||
352 | <section class="wc-backbone-modal-main" role="main"> |
||
353 | <header class="wc-backbone-modal-header"> |
||
354 | <mark class="order-status status-{{ data.status }}"><span>{{ data.status_name }}</span></mark> |
||
355 | <?php /* translators: %s: order ID */ ?> |
||
356 | <h1><?php echo esc_html( sprintf( __( 'Order #%s', 'woocommerce' ), '{{ data.order_number }}' ) ); ?></h1> |
||
357 | <button class="modal-close modal-close-link dashicons dashicons-no-alt"> |
||
358 | <span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span> |
||
359 | </button> |
||
360 | </header> |
||
361 | <article> |
||
362 | <?php do_action( 'woocommerce_admin_order_preview_start' ); ?> |
||
363 | |||
364 | <div class="wc-order-preview-addresses"> |
||
365 | <div class="wc-order-preview-address"> |
||
366 | <h2><?php esc_html_e( 'Billing details', 'woocommerce' ); ?></h2> |
||
367 | {{{ data.formatted_billing_address }}} |
||
368 | |||
369 | <# if ( data.data.billing.email ) { #> |
||
370 | <strong><?php esc_html_e( 'Email', 'woocommerce' ); ?></strong> |
||
371 | <a href="mailto:{{ data.data.billing.email }}">{{ data.data.billing.email }}</a> |
||
372 | <# } #> |
||
373 | |||
374 | <# if ( data.data.billing.phone ) { #> |
||
375 | <strong><?php esc_html_e( 'Phone', 'woocommerce' ); ?></strong> |
||
376 | <a href="tel:{{ data.data.billing.phone }}">{{ data.data.billing.phone }}</a> |
||
377 | <# } #> |
||
378 | |||
379 | <# if ( data.payment_via ) { #> |
||
380 | <strong><?php esc_html_e( 'Payment via', 'woocommerce' ); ?></strong> |
||
381 | {{{ data.payment_via }}} |
||
382 | <# } #> |
||
383 | </div> |
||
384 | <# if ( data.needs_shipping ) { #> |
||
385 | <div class="wc-order-preview-address"> |
||
386 | <h2><?php esc_html_e( 'Shipping details', 'woocommerce' ); ?></h2> |
||
387 | <# if ( data.ship_to_billing ) { #> |
||
388 | {{{ data.formatted_billing_address }}} |
||
389 | <# } else { #> |
||
390 | <a href="{{ data.shipping_address_map_url }}" target="_blank">{{{ data.formatted_shipping_address }}}</a> |
||
391 | <# } #> |
||
392 | |||
393 | <# if ( data.shipping_via ) { #> |
||
394 | <strong><?php esc_html_e( 'Shipping method', 'woocommerce' ); ?></strong> |
||
395 | {{ data.shipping_via }} |
||
396 | <# } #> |
||
397 | </div> |
||
398 | <# } #> |
||
399 | |||
400 | <# if ( data.data.customer_note ) { #> |
||
401 | <div class="wc-order-preview-note"> |
||
402 | <strong><?php esc_html_e( 'Note', 'woocommerce' ); ?></strong> |
||
403 | {{ data.data.customer_note }} |
||
404 | </div> |
||
405 | <# } #> |
||
406 | </div> |
||
407 | |||
408 | {{{ data.item_html }}} |
||
409 | |||
410 | <?php do_action( 'woocommerce_admin_order_preview_end' ); ?> |
||
411 | </article> |
||
412 | <footer> |
||
413 | <div class="inner"> |
||
414 | {{{ data.actions_html }}} |
||
415 | |||
416 | <a class="button button-primary button-large" aria-label="<?php esc_attr_e( 'Edit this order', 'woocommerce' ); ?>" href="<?php echo esc_url( admin_url( 'post.php?action=edit' ) ); ?>&post={{ data.data.id }}"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a> |
||
417 | </div> |
||
418 | </footer> |
||
419 | </section> |
||
420 | </div> |
||
421 | </div> |
||
422 | <div class="wc-backbone-modal-backdrop modal-close"></div> |
||
423 | </script> |
||
424 | <?php |
||
425 | } |
||
426 | |||
427 | /** |
||
428 | * Get items to display in the preview as HTML. |
||
429 | * |
||
430 | * @param WC_Order $order Order object. |
||
431 | * @return string |
||
432 | */ |
||
433 | public static function get_order_preview_item_html( $order ) { |
||
434 | $hidden_order_itemmeta = apply_filters( |
||
435 | 'woocommerce_hidden_order_itemmeta', |
||
436 | array( |
||
437 | '_qty', |
||
438 | '_tax_class', |
||
439 | '_product_id', |
||
440 | '_variation_id', |
||
441 | '_line_subtotal', |
||
442 | '_line_subtotal_tax', |
||
443 | '_line_total', |
||
444 | '_line_tax', |
||
445 | 'method_id', |
||
446 | 'cost', |
||
447 | '_reduced_stock', |
||
448 | ) |
||
449 | ); |
||
450 | |||
451 | $line_items = apply_filters( 'woocommerce_admin_order_preview_line_items', $order->get_items(), $order ); |
||
452 | $columns = apply_filters( |
||
453 | 'woocommerce_admin_order_preview_line_item_columns', |
||
454 | array( |
||
455 | 'product' => __( 'Product', 'woocommerce' ), |
||
456 | 'quantity' => __( 'Quantity', 'woocommerce' ), |
||
457 | 'tax' => __( 'Tax', 'woocommerce' ), |
||
458 | 'total' => __( 'Total', 'woocommerce' ), |
||
459 | ), |
||
460 | $order |
||
461 | ); |
||
462 | |||
463 | if ( ! wc_tax_enabled() ) { |
||
464 | unset( $columns['tax'] ); |
||
465 | } |
||
466 | |||
467 | $html = ' |
||
468 | <div class="wc-order-preview-table-wrapper"> |
||
469 | <table cellspacing="0" class="wc-order-preview-table"> |
||
470 | <thead> |
||
471 | <tr>'; |
||
472 | |||
473 | View Code Duplication | foreach ( $columns as $column => $label ) { |
|
474 | $html .= '<th class="wc-order-preview-table__column--' . esc_attr( $column ) . '">' . esc_html( $label ) . '</th>'; |
||
475 | } |
||
476 | |||
477 | $html .= ' |
||
478 | </tr> |
||
479 | </thead> |
||
480 | <tbody>'; |
||
481 | |||
482 | foreach ( $line_items as $item_id => $item ) { |
||
483 | |||
484 | $product_object = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : null; |
||
485 | $row_class = apply_filters( 'woocommerce_admin_html_order_preview_item_class', '', $item, $order ); |
||
486 | |||
487 | $html .= '<tr class="wc-order-preview-table__item wc-order-preview-table__item--' . esc_attr( $item_id ) . ( $row_class ? ' ' . esc_attr( $row_class ) : '' ) . '">'; |
||
488 | |||
489 | foreach ( $columns as $column => $label ) { |
||
490 | $html .= '<td class="wc-order-preview-table__column--' . esc_attr( $column ) . '">'; |
||
491 | switch ( $column ) { |
||
492 | case 'product': |
||
493 | $html .= wp_kses_post( $item->get_name() ); |
||
494 | |||
495 | if ( $product_object ) { |
||
496 | $html .= '<div class="wc-order-item-sku">' . esc_html( $product_object->get_sku() ) . '</div>'; |
||
497 | } |
||
498 | |||
499 | $meta_data = $item->get_formatted_meta_data( '' ); |
||
500 | |||
501 | if ( $meta_data ) { |
||
502 | $html .= '<table cellspacing="0" class="wc-order-item-meta">'; |
||
503 | |||
504 | foreach ( $meta_data as $meta_id => $meta ) { |
||
505 | if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) { |
||
506 | continue; |
||
507 | } |
||
508 | $html .= '<tr><th>' . wp_kses_post( $meta->display_key ) . ':</th><td>' . wp_kses_post( force_balance_tags( $meta->display_value ) ) . '</td></tr>'; |
||
509 | } |
||
510 | $html .= '</table>'; |
||
511 | } |
||
512 | break; |
||
513 | case 'quantity': |
||
514 | $html .= esc_html( $item->get_quantity() ); |
||
515 | break; |
||
516 | case 'tax': |
||
517 | $html .= wc_price( $item->get_total_tax(), array( 'currency' => $order->get_currency() ) ); |
||
518 | break; |
||
519 | case 'total': |
||
520 | $html .= wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) ); |
||
521 | break; |
||
522 | default: |
||
523 | $html .= apply_filters( 'woocommerce_admin_order_preview_line_item_column_' . sanitize_key( $column ), '', $item, $item_id, $order ); |
||
524 | break; |
||
525 | } |
||
526 | $html .= '</td>'; |
||
527 | } |
||
528 | |||
529 | $html .= '</tr>'; |
||
530 | } |
||
531 | |||
532 | $html .= ' |
||
533 | </tbody> |
||
534 | </table> |
||
535 | </div>'; |
||
536 | |||
537 | return $html; |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * Get actions to display in the preview as HTML. |
||
542 | * |
||
543 | * @param WC_Order $order Order object. |
||
544 | * @return string |
||
545 | */ |
||
546 | public static function get_order_preview_actions_html( $order ) { |
||
547 | $actions = array(); |
||
548 | $status_actions = array(); |
||
549 | |||
550 | View Code Duplication | if ( $order->has_status( array( 'pending' ) ) ) { |
|
551 | $status_actions['on-hold'] = array( |
||
552 | 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=on-hold&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ), |
||
553 | 'name' => __( 'On-hold', 'woocommerce' ), |
||
554 | 'title' => __( 'Change order status to on-hold', 'woocommerce' ), |
||
555 | 'action' => 'on-hold', |
||
556 | ); |
||
557 | } |
||
558 | |||
559 | View Code Duplication | if ( $order->has_status( array( 'pending', 'on-hold' ) ) ) { |
|
560 | $status_actions['processing'] = array( |
||
561 | 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ), |
||
562 | 'name' => __( 'Processing', 'woocommerce' ), |
||
563 | 'title' => __( 'Change order status to processing', 'woocommerce' ), |
||
564 | 'action' => 'processing', |
||
565 | ); |
||
566 | } |
||
567 | |||
568 | View Code Duplication | if ( $order->has_status( array( 'pending', 'on-hold', 'processing' ) ) ) { |
|
569 | $status_actions['complete'] = array( |
||
570 | 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ), |
||
571 | 'name' => __( 'Completed', 'woocommerce' ), |
||
572 | 'title' => __( 'Change order status to completed', 'woocommerce' ), |
||
573 | 'action' => 'complete', |
||
574 | ); |
||
575 | } |
||
576 | |||
577 | if ( $status_actions ) { |
||
0 ignored issues
–
show
|
|||
578 | $actions['status'] = array( |
||
579 | 'group' => __( 'Change status: ', 'woocommerce' ), |
||
580 | 'actions' => $status_actions, |
||
581 | ); |
||
582 | } |
||
583 | |||
584 | return wc_render_action_buttons( apply_filters( 'woocommerce_admin_order_preview_actions', $actions, $order ) ); |
||
585 | } |
||
586 | |||
587 | /** |
||
588 | * Get order details to send to the ajax endpoint for previews. |
||
589 | * |
||
590 | * @param WC_Order $order Order object. |
||
591 | * @return array |
||
592 | */ |
||
593 | public static function order_preview_get_order_details( $order ) { |
||
594 | if ( ! $order ) { |
||
595 | return array(); |
||
596 | } |
||
597 | |||
598 | $payment_via = $order->get_payment_method_title(); |
||
599 | $payment_method = $order->get_payment_method(); |
||
600 | $payment_gateways = WC()->payment_gateways() ? WC()->payment_gateways->payment_gateways() : array(); |
||
601 | $transaction_id = $order->get_transaction_id(); |
||
602 | |||
603 | View Code Duplication | if ( $transaction_id ) { |
|
604 | |||
605 | $url = isset( $payment_gateways[ $payment_method ] ) ? $payment_gateways[ $payment_method ]->get_transaction_url( $order ) : false; |
||
606 | |||
607 | if ( $url ) { |
||
608 | $payment_via .= ' (<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $transaction_id ) . '</a>)'; |
||
609 | } else { |
||
610 | $payment_via .= ' (' . esc_html( $transaction_id ) . ')'; |
||
611 | } |
||
612 | } |
||
613 | |||
614 | $billing_address = $order->get_formatted_billing_address(); |
||
615 | $shipping_address = $order->get_formatted_shipping_address(); |
||
616 | |||
617 | return apply_filters( |
||
618 | 'woocommerce_admin_order_preview_get_order_details', |
||
619 | array( |
||
620 | 'data' => $order->get_data(), |
||
621 | 'order_number' => $order->get_order_number(), |
||
622 | 'item_html' => self::get_order_preview_item_html( $order ), |
||
623 | 'actions_html' => self::get_order_preview_actions_html( $order ), |
||
624 | 'ship_to_billing' => wc_ship_to_billing_address_only(), |
||
625 | 'needs_shipping' => $order->needs_shipping_address(), |
||
626 | 'formatted_billing_address' => $billing_address ? $billing_address : __( 'N/A', 'woocommerce' ), |
||
627 | 'formatted_shipping_address' => $shipping_address ? $shipping_address : __( 'N/A', 'woocommerce' ), |
||
628 | 'shipping_address_map_url' => $order->get_shipping_address_map_url(), |
||
629 | 'payment_via' => $payment_via, |
||
630 | 'shipping_via' => $order->get_shipping_method(), |
||
631 | 'status' => $order->get_status(), |
||
632 | 'status_name' => wc_get_order_status_name( $order->get_status() ), |
||
633 | ), |
||
634 | $order |
||
635 | ); |
||
636 | } |
||
637 | |||
638 | /** |
||
639 | * Handle bulk actions. |
||
640 | * |
||
641 | * @param string $redirect_to URL to redirect to. |
||
642 | * @param string $action Action name. |
||
643 | * @param array $ids List of ids. |
||
644 | * @return string |
||
645 | */ |
||
646 | public function handle_bulk_actions( $redirect_to, $action, $ids ) { |
||
647 | $ids = apply_filters( 'woocommerce_bulk_action_ids', array_reverse( array_map( 'absint', $ids ) ), $action, 'order' ); |
||
648 | $changed = 0; |
||
649 | |||
650 | if ( 'remove_personal_data' === $action ) { |
||
651 | $report_action = 'removed_personal_data'; |
||
652 | |||
653 | foreach ( $ids as $id ) { |
||
654 | $order = wc_get_order( $id ); |
||
655 | |||
656 | if ( $order ) { |
||
657 | do_action( 'woocommerce_remove_order_personal_data', $order ); |
||
658 | $changed++; |
||
659 | } |
||
660 | } |
||
661 | } elseif ( false !== strpos( $action, 'mark_' ) ) { |
||
662 | $order_statuses = wc_get_order_statuses(); |
||
663 | $new_status = substr( $action, 5 ); // Get the status name from action. |
||
664 | $report_action = 'marked_' . $new_status; |
||
665 | |||
666 | // Sanity check: bail out if this is actually not a status, or is not a registered status. |
||
667 | if ( isset( $order_statuses[ 'wc-' . $new_status ] ) ) { |
||
668 | // Initialize payment gateways in case order has hooked status transition actions. |
||
669 | WC()->payment_gateways(); |
||
670 | |||
671 | foreach ( $ids as $id ) { |
||
672 | $order = wc_get_order( $id ); |
||
673 | $order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ), true ); |
||
674 | do_action( 'woocommerce_order_edit_status', $id, $new_status ); |
||
675 | $changed++; |
||
676 | } |
||
677 | } |
||
678 | } |
||
679 | |||
680 | if ( $changed ) { |
||
681 | $redirect_to = add_query_arg( |
||
682 | array( |
||
683 | 'post_type' => $this->list_table_type, |
||
684 | 'bulk_action' => $report_action, |
||
685 | 'changed' => $changed, |
||
686 | 'ids' => join( ',', $ids ), |
||
687 | ), |
||
688 | $redirect_to |
||
689 | ); |
||
690 | } |
||
691 | |||
692 | return esc_url_raw( $redirect_to ); |
||
693 | } |
||
694 | |||
695 | /** |
||
696 | * Show confirmation message that order status changed for number of orders. |
||
697 | */ |
||
698 | public function bulk_admin_notices() { |
||
699 | global $post_type, $pagenow; |
||
700 | |||
701 | // Bail out if not on shop order list page. |
||
702 | if ( 'edit.php' !== $pagenow || 'shop_order' !== $post_type || ! isset( $_REQUEST['bulk_action'] ) ) { // WPCS: input var ok, CSRF ok. |
||
703 | return; |
||
704 | } |
||
705 | |||
706 | $order_statuses = wc_get_order_statuses(); |
||
707 | $number = isset( $_REQUEST['changed'] ) ? absint( $_REQUEST['changed'] ) : 0; // WPCS: input var ok, CSRF ok. |
||
708 | $bulk_action = wc_clean( wp_unslash( $_REQUEST['bulk_action'] ) ); // WPCS: input var ok, CSRF ok. |
||
709 | |||
710 | // Check if any status changes happened. |
||
711 | foreach ( $order_statuses as $slug => $name ) { |
||
712 | View Code Duplication | if ( 'marked_' . str_replace( 'wc-', '', $slug ) === $bulk_action ) { // WPCS: input var ok, CSRF ok. |
|
713 | /* translators: %d: orders count */ |
||
714 | $message = sprintf( _n( '%d order status changed.', '%d order statuses changed.', $number, 'woocommerce' ), number_format_i18n( $number ) ); |
||
715 | echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>'; |
||
716 | break; |
||
717 | } |
||
718 | } |
||
719 | |||
720 | View Code Duplication | if ( 'removed_personal_data' === $bulk_action ) { // WPCS: input var ok, CSRF ok. |
|
721 | /* translators: %d: orders count */ |
||
722 | $message = sprintf( _n( 'Removed personal data from %d order.', 'Removed personal data from %d orders.', $number, 'woocommerce' ), number_format_i18n( $number ) ); |
||
723 | echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>'; |
||
724 | } |
||
725 | } |
||
726 | |||
727 | /** |
||
728 | * See if we should render search filters or not. |
||
729 | */ |
||
730 | public function restrict_manage_posts() { |
||
731 | global $typenow; |
||
732 | |||
733 | if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) { |
||
734 | $this->render_filters(); |
||
735 | } |
||
736 | } |
||
737 | |||
738 | /** |
||
739 | * Render any custom filters and search inputs for the list table. |
||
740 | */ |
||
741 | protected function render_filters() { |
||
742 | $user_string = ''; |
||
743 | $user_id = ''; |
||
744 | |||
745 | if ( ! empty( $_GET['_customer_user'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification |
||
746 | $user_id = absint( $_GET['_customer_user'] ); // WPCS: input var ok, sanitization ok. |
||
747 | $user = get_user_by( 'id', $user_id ); |
||
748 | |||
749 | $user_string = sprintf( |
||
750 | /* translators: 1: user display name 2: user ID 3: user email */ |
||
751 | esc_html__( '%1$s (#%2$s – %3$s)', 'woocommerce' ), |
||
752 | $user->display_name, |
||
753 | absint( $user->ID ), |
||
754 | $user->user_email |
||
755 | ); |
||
756 | } |
||
757 | ?> |
||
758 | <select class="wc-customer-search" name="_customer_user" data-placeholder="<?php esc_attr_e( 'Filter by registered customer', 'woocommerce' ); ?>" data-allow_clear="true"> |
||
759 | <option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo htmlspecialchars( wp_kses_post( $user_string ) ); // htmlspecialchars to prevent XSS when rendered by selectWoo. ?><option> |
||
760 | </select> |
||
761 | <?php |
||
762 | } |
||
763 | |||
764 | /** |
||
765 | * Handle any filters. |
||
766 | * |
||
767 | * @param array $query_vars Query vars. |
||
768 | * @return array |
||
769 | */ |
||
770 | public function request_query( $query_vars ) { |
||
771 | global $typenow; |
||
772 | |||
773 | if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) { |
||
774 | return $this->query_filters( $query_vars ); |
||
775 | } |
||
776 | |||
777 | return $query_vars; |
||
778 | } |
||
779 | |||
780 | /** |
||
781 | * Handle any custom filters. |
||
782 | * |
||
783 | * @param array $query_vars Query vars. |
||
784 | * @return array |
||
785 | */ |
||
786 | protected function query_filters( $query_vars ) { |
||
787 | global $wp_post_statuses; |
||
788 | |||
789 | // Filter the orders by the posted customer. |
||
790 | View Code Duplication | if ( ! empty( $_GET['_customer_user'] ) ) { // WPCS: input var ok. |
|
791 | // @codingStandardsIgnoreStart. |
||
792 | $query_vars['meta_query'] = array( |
||
793 | array( |
||
794 | 'key' => '_customer_user', |
||
795 | 'value' => (int) $_GET['_customer_user'], // WPCS: input var ok, sanitization ok. |
||
796 | 'compare' => '=', |
||
797 | ), |
||
798 | ); |
||
799 | // @codingStandardsIgnoreEnd |
||
800 | } |
||
801 | |||
802 | // Sorting. |
||
803 | if ( isset( $query_vars['orderby'] ) ) { |
||
804 | if ( 'order_total' === $query_vars['orderby'] ) { |
||
805 | // @codingStandardsIgnoreStart |
||
806 | $query_vars = array_merge( $query_vars, array( |
||
807 | 'meta_key' => '_order_total', |
||
808 | 'orderby' => 'meta_value_num', |
||
809 | ) ); |
||
810 | // @codingStandardsIgnoreEnd |
||
811 | } |
||
812 | } |
||
813 | |||
814 | // Status. |
||
815 | if ( empty( $query_vars['post_status'] ) ) { |
||
816 | $post_statuses = wc_get_order_statuses(); |
||
817 | |||
818 | foreach ( $post_statuses as $status => $value ) { |
||
819 | if ( isset( $wp_post_statuses[ $status ] ) && false === $wp_post_statuses[ $status ]->show_in_admin_all_list ) { |
||
820 | unset( $post_statuses[ $status ] ); |
||
821 | } |
||
822 | } |
||
823 | |||
824 | $query_vars['post_status'] = array_keys( $post_statuses ); |
||
825 | } |
||
826 | return $query_vars; |
||
827 | } |
||
828 | |||
829 | /** |
||
830 | * Change the label when searching orders. |
||
831 | * |
||
832 | * @param mixed $query Current search query. |
||
833 | * @return string |
||
834 | */ |
||
835 | View Code Duplication | public function search_label( $query ) { |
|
836 | global $pagenow, $typenow; |
||
837 | |||
838 | if ( 'edit.php' !== $pagenow || 'shop_order' !== $typenow || ! get_query_var( 'shop_order_search' ) || ! isset( $_GET['s'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification |
||
839 | return $query; |
||
840 | } |
||
841 | |||
842 | return wc_clean( wp_unslash( $_GET['s'] ) ); // WPCS: input var ok, sanitization ok. |
||
843 | } |
||
844 | |||
845 | /** |
||
846 | * Query vars for custom searches. |
||
847 | * |
||
848 | * @param mixed $public_query_vars Array of query vars. |
||
849 | * @return array |
||
850 | */ |
||
851 | public function add_custom_query_var( $public_query_vars ) { |
||
852 | $public_query_vars[] = 'shop_order_search'; |
||
853 | return $public_query_vars; |
||
854 | } |
||
855 | |||
856 | /** |
||
857 | * Search custom fields as well as content. |
||
858 | * |
||
859 | * @param WP_Query $wp Query object. |
||
860 | */ |
||
861 | public function search_custom_fields( $wp ) { |
||
862 | global $pagenow; |
||
863 | |||
864 | if ( 'edit.php' !== $pagenow || empty( $wp->query_vars['s'] ) || 'shop_order' !== $wp->query_vars['post_type'] || ! isset( $_GET['s'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification |
||
865 | return; |
||
866 | } |
||
867 | |||
868 | $post_ids = wc_order_search( wc_clean( wp_unslash( $_GET['s'] ) ) ); // WPCS: input var ok, sanitization ok. |
||
869 | |||
870 | if ( ! empty( $post_ids ) ) { |
||
871 | // Remove "s" - we don't want to search order name. |
||
872 | unset( $wp->query_vars['s'] ); |
||
873 | |||
874 | // so we know we're doing this. |
||
875 | $wp->query_vars['shop_order_search'] = true; |
||
876 | |||
877 | // Search by found posts. |
||
878 | $wp->query_vars['post__in'] = array_merge( $post_ids, array( 0 ) ); |
||
879 | } |
||
880 | } |
||
881 | } |
||
882 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.