ID, 'manageedit-shop_ordercolumnshidden', array( 0 => 'billing_address' ), true ); } // Show blank state add_action( 'manage_posts_extra_tablenav', array( $this, 'maybe_render_blank_state' ) ); // Hide template for CPT archive. add_filter( 'theme_page_templates', array( $this, 'hide_cpt_archive_templates' ), 10, 3 ); add_action( 'edit_form_top', array( $this, 'show_cpt_archive_notice' ) ); } /** * Change messages when a post type is updated. * @param array $messages * @return array */ public function post_updated_messages( $messages ) { global $post, $post_ID; $messages['product'] = array( 0 => '', // Unused. Messages start at index 1. 1 => sprintf( __( 'Product updated. View Product', 'woocommerce' ), esc_url( get_permalink( $post_ID ) ) ), 2 => __( 'Custom field updated.', 'woocommerce' ), 3 => __( 'Custom field deleted.', 'woocommerce' ), 4 => __( 'Product updated.', 'woocommerce' ), /* translators: %s: revision title */ 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Product restored to revision from %s', 'woocommerce' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, /* translators: %s: product url */ 6 => sprintf( __( 'Product published. View Product', 'woocommerce' ), esc_url( get_permalink( $post_ID ) ) ), 7 => __( 'Product saved.', 'woocommerce' ), /* translators: %s: product url */ 8 => sprintf( __( 'Product submitted. Preview product', 'woocommerce' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ), /* translators: 1: date 2: product url */ 9 => sprintf( __( 'Product scheduled for: %1$s. Preview product', 'woocommerce' ), date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post_ID ) ) ), /* translators: %s: product url */ 10 => sprintf( __( 'Product draft updated. Preview product', 'woocommerce' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ), ); $messages['shop_order'] = array( 0 => '', // Unused. Messages start at index 1. 1 => __( 'Order updated.', 'woocommerce' ), 2 => __( 'Custom field updated.', 'woocommerce' ), 3 => __( 'Custom field deleted.', 'woocommerce' ), 4 => __( 'Order updated.', 'woocommerce' ), /* translators: %s: revision title */ 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Order restored to revision from %s', 'woocommerce' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, 6 => __( 'Order updated.', 'woocommerce' ), 7 => __( 'Order saved.', 'woocommerce' ), 8 => __( 'Order submitted.', 'woocommerce' ), /* translators: %s: date */ 9 => sprintf( __( 'Order scheduled for: %1$s.', 'woocommerce' ), date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $post->post_date ) ) ), 10 => __( 'Order draft updated.', 'woocommerce' ), 11 => __( 'Order updated and email sent.', 'woocommerce' ), ); $messages['shop_coupon'] = array( 0 => '', // Unused. Messages start at index 1. 1 => __( 'Coupon updated.', 'woocommerce' ), 2 => __( 'Custom field updated.', 'woocommerce' ), 3 => __( 'Custom field deleted.', 'woocommerce' ), 4 => __( 'Coupon updated.', 'woocommerce' ), /* translators: %s: revision title */ 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Coupon restored to revision from %s', 'woocommerce' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, 6 => __( 'Coupon updated.', 'woocommerce' ), 7 => __( 'Coupon saved.', 'woocommerce' ), 8 => __( 'Coupon submitted.', 'woocommerce' ), /* translators: %s: date */ 9 => sprintf( __( 'Coupon scheduled for: %1$s.', 'woocommerce' ), date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $post->post_date ) ) ), 10 => __( 'Coupon draft updated.', 'woocommerce' ), ); return $messages; } /** * Specify custom bulk actions messages for different post types. * @param array $bulk_messages * @param array $bulk_counts * @return array */ public function bulk_post_updated_messages( $bulk_messages, $bulk_counts ) { $bulk_messages['product'] = array( /* translators: %s: product count */ 'updated' => _n( '%s product updated.', '%s products updated.', $bulk_counts['updated'], 'woocommerce' ), /* translators: %s: product count */ 'locked' => _n( '%s product not updated, somebody is editing it.', '%s products not updated, somebody is editing them.', $bulk_counts['locked'], 'woocommerce' ), /* translators: %s: product count */ 'deleted' => _n( '%s product permanently deleted.', '%s products permanently deleted.', $bulk_counts['deleted'], 'woocommerce' ), /* translators: %s: product count */ 'trashed' => _n( '%s product moved to the Trash.', '%s products moved to the Trash.', $bulk_counts['trashed'], 'woocommerce' ), /* translators: %s: product count */ 'untrashed' => _n( '%s product restored from the Trash.', '%s products restored from the Trash.', $bulk_counts['untrashed'], 'woocommerce' ), ); $bulk_messages['shop_order'] = array( /* translators: %s: order count */ 'updated' => _n( '%s order updated.', '%s orders updated.', $bulk_counts['updated'], 'woocommerce' ), /* translators: %s: order count */ 'locked' => _n( '%s order not updated, somebody is editing it.', '%s orders not updated, somebody is editing them.', $bulk_counts['locked'], 'woocommerce' ), /* translators: %s: order count */ 'deleted' => _n( '%s order permanently deleted.', '%s orders permanently deleted.', $bulk_counts['deleted'], 'woocommerce' ), /* translators: %s: order count */ 'trashed' => _n( '%s order moved to the Trash.', '%s orders moved to the Trash.', $bulk_counts['trashed'], 'woocommerce' ), /* translators: %s: order count */ 'untrashed' => _n( '%s order restored from the Trash.', '%s orders restored from the Trash.', $bulk_counts['untrashed'], 'woocommerce' ), ); $bulk_messages['shop_coupon'] = array( /* translators: %s: coupon count */ 'updated' => _n( '%s coupon updated.', '%s coupons updated.', $bulk_counts['updated'], 'woocommerce' ), /* translators: %s: coupon count */ 'locked' => _n( '%s coupon not updated, somebody is editing it.', '%s coupons not updated, somebody is editing them.', $bulk_counts['locked'], 'woocommerce' ), /* translators: %s: coupon count */ 'deleted' => _n( '%s coupon permanently deleted.', '%s coupons permanently deleted.', $bulk_counts['deleted'], 'woocommerce' ), /* translators: %s: coupon count */ 'trashed' => _n( '%s coupon moved to the Trash.', '%s coupons moved to the Trash.', $bulk_counts['trashed'], 'woocommerce' ), /* translators: %s: coupon count */ 'untrashed' => _n( '%s coupon restored from the Trash.', '%s coupons restored from the Trash.', $bulk_counts['untrashed'], 'woocommerce' ), ); return $bulk_messages; } /** * Define custom columns for products. * @param array $existing_columns * @return array */ public function product_columns( $existing_columns ) { if ( empty( $existing_columns ) && ! is_array( $existing_columns ) ) { $existing_columns = array(); } unset( $existing_columns['title'], $existing_columns['comments'], $existing_columns['date'] ); $columns = array(); $columns['cb'] = ''; $columns['thumb'] = '' . __( 'Image', 'woocommerce' ) . ''; $columns['name'] = __( 'Name', 'woocommerce' ); if ( wc_product_sku_enabled() ) { $columns['sku'] = __( 'SKU', 'woocommerce' ); } if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) { $columns['is_in_stock'] = __( 'Stock', 'woocommerce' ); } $columns['price'] = __( 'Price', 'woocommerce' ); $columns['product_cat'] = __( 'Categories', 'woocommerce' ); $columns['product_tag'] = __( 'Tags', 'woocommerce' ); $columns['featured'] = '' . __( 'Featured', 'woocommerce' ) . ''; $columns['product_type'] = '' . __( 'Type', 'woocommerce' ) . ''; $columns['date'] = __( 'Date', 'woocommerce' ); return array_merge( $columns, $existing_columns ); } /** * Define custom columns for coupons. * @param array $existing_columns * @return array */ public function shop_coupon_columns( $existing_columns ) { $columns = array(); $columns['cb'] = $existing_columns['cb']; $columns['coupon_code'] = __( 'Code', 'woocommerce' ); $columns['type'] = __( 'Coupon type', 'woocommerce' ); $columns['amount'] = __( 'Coupon amount', 'woocommerce' ); $columns['description'] = __( 'Description', 'woocommerce' ); $columns['products'] = __( 'Product IDs', 'woocommerce' ); $columns['usage'] = __( 'Usage / Limit', 'woocommerce' ); $columns['expiry_date'] = __( 'Expiry date', 'woocommerce' ); return $columns; } /** * Define custom columns for orders. * @param array $existing_columns * @return array */ public function shop_order_columns( $existing_columns ) { $columns = array(); $columns['cb'] = $existing_columns['cb']; $columns['order_status'] = '' . esc_attr__( 'Status', 'woocommerce' ) . ''; $columns['order_title'] = __( 'Order', 'woocommerce' ); $columns['order_items'] = __( 'Purchased', 'woocommerce' ); $columns['billing_address'] = __( 'Billing', 'woocommerce' ); $columns['shipping_address'] = __( 'Ship to', 'woocommerce' ); $columns['customer_message'] = '' . esc_attr__( 'Customer message', 'woocommerce' ) . ''; $columns['order_notes'] = '' . esc_attr__( 'Order notes', 'woocommerce' ) . ''; $columns['order_date'] = __( 'Date', 'woocommerce' ); $columns['order_total'] = __( 'Total', 'woocommerce' ); $columns['order_actions'] = __( 'Actions', 'woocommerce' ); return $columns; } /** * Ouput custom columns for products. * * @param string $column */ public function render_product_columns( $column ) { global $post, $the_product; if ( empty( $the_product ) || $the_product->id != $post->ID ) { $the_product = wc_get_product( $post ); } switch ( $column ) { case 'thumb' : echo '' . $the_product->get_image( 'thumbnail' ) . ''; break; case 'name' : $edit_link = get_edit_post_link( $post->ID ); $title = _draft_or_post_title(); echo '' . esc_html( $title ) . ''; _post_states( $post ); echo ''; if ( $post->post_parent > 0 ) { echo '  ← ' . get_the_title( $post->post_parent ) . ''; } // Excerpt view if ( isset( $_GET['mode'] ) && 'excerpt' == $_GET['mode'] ) { echo apply_filters( 'the_excerpt', $post->post_excerpt ); } $this->_render_product_row_actions( $post, $title ); get_inline_data( $post ); /* Custom inline data for woocommerce. */ echo ' '; break; case 'sku' : echo $the_product->get_sku() ? $the_product->get_sku() : ''; break; case 'product_type' : if ( 'grouped' == $the_product->product_type ) { echo ''; } elseif ( 'external' == $the_product->product_type ) { echo ''; } elseif ( 'simple' == $the_product->product_type ) { if ( $the_product->is_virtual() ) { echo ''; } elseif ( $the_product->is_downloadable() ) { echo ''; } else { echo ''; } } elseif ( 'variable' == $the_product->product_type ) { echo ''; } else { // Assuming that we have other types in future echo ''; } break; case 'price' : echo $the_product->get_price_html() ? $the_product->get_price_html() : ''; break; case 'product_cat' : case 'product_tag' : if ( ! $terms = get_the_terms( $post->ID, $column ) ) { echo ''; } else { $termlist = array(); foreach ( $terms as $term ) { $termlist[] = '' . $term->name . ''; } echo implode( ', ', $termlist ); } break; case 'featured' : $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_feature_product&product_id=' . $post->ID ), 'woocommerce-feature-product' ); echo ''; if ( $the_product->is_featured() ) { echo '' . __( 'Yes', 'woocommerce' ) . ''; } else { echo '' . __( 'No', 'woocommerce' ) . ''; } echo ''; break; case 'is_in_stock' : if ( $the_product->is_in_stock() ) { $stock_html = '' . __( 'In stock', 'woocommerce' ) . ''; } else { $stock_html = '' . __( 'Out of stock', 'woocommerce' ) . ''; } // If the product has children, a single stock level would be misleading as some could be -ve and some +ve, some managed/some unmanaged etc so hide stock level in this case. if ( $the_product->managing_stock() && ! sizeof( $the_product->get_children() ) ) { $stock_html .= ' (' . $the_product->get_total_stock() . ')'; } echo apply_filters( 'woocommerce_admin_stock_html', $stock_html, $the_product ); break; default : break; } } /** * Render product row actions for old version of WordPress. * Since WordPress 4.3 we don't have to build the row actions. * * @param WP_Post $post * @param string $title */ private function _render_product_row_actions( $post, $title ) { global $wp_version; if ( version_compare( $wp_version, '4.3-beta', '>=' ) ) { return; } $post_type_object = get_post_type_object( $post->post_type ); $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); // Get actions $actions = array(); $actions['id'] = 'ID: ' . $post->ID; if ( $can_edit_post && 'trash' != $post->post_status ) { $actions['edit'] = '' . __( 'Edit', 'woocommerce' ) . ''; $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit', 'woocommerce' ) . ''; } if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { if ( 'trash' == $post->post_status ) { $actions['untrash'] = '' . __( 'Restore', 'woocommerce' ) . ''; } elseif ( EMPTY_TRASH_DAYS ) { $actions['trash'] = '' . __( 'Trash', 'woocommerce' ) . ''; } if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) { $actions['delete'] = '' . __( 'Delete permanently', 'woocommerce' ) . ''; } } if ( $post_type_object->public ) { if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { if ( $can_edit_post ) { /* translators: %s: product title */ $actions['view'] = '' . __( 'Preview', 'woocommerce' ) . ''; } } elseif ( 'trash' != $post->post_status ) { /* translators: %s: product title */ $actions['view'] = '' . __( 'View', 'woocommerce' ) . ''; } } $actions = apply_filters( 'post_row_actions', $actions, $post ); echo '
'; $i = 0; $action_count = sizeof( $actions ); foreach ( $actions as $action => $link ) { ++$i; ( $i == $action_count ) ? $sep = '' : $sep = ' | '; echo '' . $link . $sep . ''; } echo '
'; } /** * Output custom columns for coupons. * * @param string $column */ public function render_shop_coupon_columns( $column ) { global $post, $woocommerce; switch ( $column ) { case 'coupon_code' : $edit_link = get_edit_post_link( $post->ID ); $title = _draft_or_post_title(); echo '' . esc_html( $title ) . ''; _post_states( $post ); echo ''; $this->_render_shop_coupon_row_actions( $post, $title ); break; case 'type' : echo esc_html( wc_get_coupon_type( get_post_meta( $post->ID, 'discount_type', true ) ) ); break; case 'amount' : echo esc_html( get_post_meta( $post->ID, 'coupon_amount', true ) ); break; case 'products' : $product_ids = get_post_meta( $post->ID, 'product_ids', true ); $product_ids = $product_ids ? array_map( 'absint', explode( ',', $product_ids ) ) : array(); if ( sizeof( $product_ids ) > 0 ) { echo esc_html( implode( ', ', $product_ids ) ); } else { echo '–'; } break; case 'usage_limit' : $usage_limit = get_post_meta( $post->ID, 'usage_limit', true ); if ( $usage_limit ) { echo esc_html( $usage_limit ); } else { echo '–'; } break; case 'usage' : $usage_count = absint( get_post_meta( $post->ID, 'usage_count', true ) ); $usage_limit = esc_html( get_post_meta( $post->ID, 'usage_limit', true ) ); $usage_url = sprintf( '%s', admin_url( sprintf( 'edit.php?s=%s&post_status=all&post_type=shop_order', esc_html( $post->post_title ) ) ), $usage_count ); /* translators: 1: count 2: limit */ printf( __( '%1$s / %2$s', 'woocommerce' ), $usage_url, $usage_limit ? $usage_limit : '∞' ); break; case 'expiry_date' : $expiry_date = get_post_meta( $post->ID, 'expiry_date', true ); if ( $expiry_date ) { echo esc_html( date_i18n( 'F j, Y', strtotime( $expiry_date ) ) ); } else { echo '–'; } break; case 'description' : echo wp_kses_post( $post->post_excerpt ); break; } } /** * Render shop_coupon row actions for old version of WordPress. * Since WordPress 4.3 we don't have to build the row actions. * * @param WP_Post $post * @param string $title */ private function _render_shop_coupon_row_actions( $post, $title ) { global $wp_version; if ( version_compare( $wp_version, '4.3-beta', '>=' ) ) { return; } $post_type_object = get_post_type_object( $post->post_type ); // Get actions $actions = array(); if ( current_user_can( $post_type_object->cap->edit_post, $post->ID ) ) { $actions['edit'] = '' . __( 'Edit', 'woocommerce' ) . ''; } if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { if ( 'trash' == $post->post_status ) { $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore', 'woocommerce' ) . ""; } elseif ( EMPTY_TRASH_DAYS ) { $actions['trash'] = "" . __( 'Trash', 'woocommerce' ) . ""; } if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) { $actions['delete'] = "" . __( 'Delete permanently', 'woocommerce' ) . ""; } } $actions = apply_filters( 'post_row_actions', $actions, $post ); echo '
'; $i = 0; $action_count = sizeof( $actions ); foreach ( $actions as $action => $link ) { ++$i; ( $i == $action_count ) ? $sep = '' : $sep = ' | '; echo "$link$sep"; } echo '
'; } /** * Output custom columns for coupons. * @param string $column */ public function render_shop_order_columns( $column ) { global $post, $woocommerce, $the_order; if ( empty( $the_order ) || $the_order->get_id() != $post->ID ) { $the_order = wc_get_order( $post->ID ); } switch ( $column ) { case 'order_status' : printf( '%s', sanitize_title( $the_order->get_status() ), wc_get_order_status_name( $the_order->get_status() ), wc_get_order_status_name( $the_order->get_status() ) ); break; case 'order_date' : if ( '0000-00-00 00:00:00' == $post->post_date ) { $t_time = $h_time = __( 'Unpublished', 'woocommerce' ); } else { $t_time = get_the_time( __( 'Y/m/d g:i:s A', 'woocommerce' ), $post ); $h_time = get_the_time( __( 'Y/m/d', 'woocommerce' ), $post ); } echo '' . esc_html( apply_filters( 'post_date_column_time', $h_time, $post ) ) . ''; break; case 'customer_message' : if ( $the_order->get_customer_note() ) { echo '' . __( 'Yes', 'woocommerce' ) . ''; } else { echo ''; } break; case 'order_items' : /* translators: %d: order items count */ echo '' . apply_filters( 'woocommerce_admin_order_item_count', sprintf( _n( '%d item', '%d items', $the_order->get_item_count(), 'woocommerce' ), $the_order->get_item_count() ), $the_order ) . ''; if ( sizeof( $the_order->get_items() ) > 0 ) { echo ''; foreach ( $the_order->get_items() as $item ) { $product = apply_filters( 'woocommerce_order_item_product', $item->get_product(), $item ); $item_meta = new WC_Order_Item_Meta( $item, $product ); $item_meta_html = $item_meta->display( true, true ); ?> '; } else echo '–'; break; case 'billing_address' : if ( $address = $the_order->get_formatted_billing_address() ) { echo esc_html( preg_replace( '##i', ', ', $address ) ); } else { echo '–'; } if ( $the_order->get_billing_phone() ) { echo '' . __( 'Phone:', 'woocommerce' ) . ' ' . esc_html( $the_order->get_billing_phone() ) . ''; } break; case 'shipping_address' : if ( $address = $the_order->get_formatted_shipping_address() ) { echo '' . esc_html( preg_replace( '##i', ', ', $address ) ) . ''; } else { echo '–'; } if ( $the_order->get_shipping_method() ) { echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->get_shipping_method() ) . ''; } break; case 'order_notes' : if ( $post->comment_count ) { // check the status of the post $status = ( 'trash' !== $post->post_status ) ? '' : 'post-trashed'; $latest_notes = get_comments( array( 'post_id' => $post->ID, 'number' => 1, 'status' => $status, ) ); $latest_note = current( $latest_notes ); if ( isset( $latest_note->comment_content ) && 1 == $post->comment_count ) { echo '' . __( 'Yes', 'woocommerce' ) . ''; } elseif ( isset( $latest_note->comment_content ) ) { /* translators: %d: notes count */ echo '' . sprintf( _n( 'plus %d other note', 'plus %d other notes', ( $post->comment_count - 1 ), 'woocommerce' ), $post->comment_count - 1 ) . '' ) . '">' . __( 'Yes', 'woocommerce' ) . ''; } else { /* translators: %d: notes count */ echo '' . __( 'Yes', 'woocommerce' ) . ''; } } else { echo ''; } break; case 'order_total' : echo $the_order->get_formatted_order_total(); if ( $the_order->get_payment_method_title() ) { echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->get_payment_method_title() ) . ''; } break; case 'order_title' : if ( $the_order->get_user_id() ) { $user_info = get_userdata( $the_order->get_user_id() ); } if ( ! empty( $user_info ) ) { $username = ''; if ( $user_info->first_name || $user_info->last_name ) { /* translators: 1: first name 2: last name */ $username .= esc_html( sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), ucfirst( $user_info->first_name ), ucfirst( $user_info->last_name ) ) ); } else { $username .= esc_html( ucfirst( $user_info->display_name ) ); } $username .= ''; } else { if ( $the_order->get_billing_first_name()|| $the_order->get_billing_last_name() ) { /* translators: 1: first name 2: last name */ $username = trim( sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $the_order->get_billing_first_name(), $the_order->get_billing_last_name() ) ); } elseif ( $the_order->get_billing_company() ) { $username = trim( $the_order->get_billing_company() ); } else { $username = __( 'Guest', 'woocommerce' ); } } /* translators: 1: order and number (i.e. Order #13) 2: user name */ printf( __( '%1$s by %2$s', 'woocommerce' ), '#' . esc_attr( $the_order->get_order_number() ) . '', $username ); if ( $the_order->get_billing_email() ) { echo '' . esc_html( $the_order->get_billing_email() ) . ''; } echo ''; break; case 'order_actions' : ?>

has_status( array( 'pending', 'on-hold' ) ) ) { $actions['processing'] = array( 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $post->ID ), 'woocommerce-mark-order-status' ), 'name' => __( 'Processing', 'woocommerce' ), 'action' => "processing", ); } if ( $the_order->has_status( array( 'pending', 'on-hold', 'processing' ) ) ) { $actions['complete'] = array( 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $post->ID ), 'woocommerce-mark-order-status' ), 'name' => __( 'Complete', 'woocommerce' ), 'action' => "complete", ); } $actions['view'] = array( 'url' => admin_url( 'post.php?post=' . $post->ID . '&action=edit' ), 'name' => __( 'View', 'woocommerce' ), 'action' => "view", ); $actions = apply_filters( 'woocommerce_admin_order_actions', $actions, $the_order ); foreach ( $actions as $action ) { printf( '%s', esc_attr( $action['action'] ), esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_attr( $action['name'] ) ); } do_action( 'woocommerce_admin_order_actions_end', $the_order ); ?>

'price', 'featured' => array( 'featured', 1 ), 'sku' => 'sku', 'name' => 'title', ); return wp_parse_args( $custom, $columns ); } /** * Make columns sortable - https://gist.github.com/906872. * * @param array $columns * @return array */ public function shop_coupon_sortable_columns( $columns ) { return $columns; } /** * Make columns sortable - https://gist.github.com/906872. * * @param array $columns * @return array */ public function shop_order_sortable_columns( $columns ) { $custom = array( 'order_title' => 'ID', 'order_total' => 'order_total', 'order_date' => 'date', ); unset( $columns['comments'] ); return wp_parse_args( $custom, $columns ); } /** * Remove edit from the bulk actions. * * @param array $actions * @return array */ public function shop_order_bulk_actions( $actions ) { if ( isset( $actions['edit'] ) ) { unset( $actions['edit'] ); } return $actions; } /** * Set list table primary column for products and orders. * Support for WordPress 4.3. * * @param string $default * @param string $screen_id * * @return string */ public function list_table_primary_column( $default, $screen_id ) { if ( 'edit-product' === $screen_id ) { return 'name'; } if ( 'edit-shop_order' === $screen_id ) { return 'order_title'; } if ( 'edit-shop_coupon' === $screen_id ) { return 'coupon_code'; } return $default; } /** * Set row actions for products and orders. * * @param array $actions * @param WP_Post $post * * @return array */ public function row_actions( $actions, $post ) { if ( 'product' === $post->post_type ) { return array_merge( array( 'id' => 'ID: ' . $post->ID ), $actions ); } if ( in_array( $post->post_type, array( 'shop_order', 'shop_coupon' ) ) ) { if ( isset( $actions['inline hide-if-no-js'] ) ) { unset( $actions['inline hide-if-no-js'] ); } } return $actions; } /** * Product sorting link. * * Based on Simple Page Ordering by 10up (https://wordpress.org/plugins/simple-page-ordering/). * * @param array $views * @return array */ public function product_sorting_link( $views ) { global $post_type, $wp_query; if ( ! current_user_can( 'edit_others_pages' ) ) { return $views; } $class = ( isset( $wp_query->query['orderby'] ) && 'menu_order title' === $wp_query->query['orderby'] ) ? 'current' : ''; $query_string = remove_query_arg( array( 'orderby', 'order' ) ); $query_string = add_query_arg( 'orderby', urlencode( 'menu_order title' ), $query_string ); $query_string = add_query_arg( 'order', urlencode( 'ASC' ), $query_string ); $views['byorder'] = '' . __( 'Sort products', 'woocommerce' ) . ''; return $views; } /** * Custom bulk edit - form. * * @param mixed $column_name * @param mixed $post_type */ public function bulk_edit( $column_name, $post_type ) { if ( 'price' != $column_name || 'product' != $post_type ) { return; } $shipping_class = get_terms( 'product_shipping_class', array( 'hide_empty' => false, ) ); include( WC()->plugin_path() . '/includes/admin/views/html-bulk-edit-product.php' ); } /** * Custom quick edit - form. * * @param mixed $column_name * @param mixed $post_type */ public function quick_edit( $column_name, $post_type ) { if ( 'price' != $column_name || 'product' != $post_type ) { return; } $shipping_class = get_terms( 'product_shipping_class', array( 'hide_empty' => false, ) ); include( WC()->plugin_path() . '/includes/admin/views/html-quick-edit-product.php' ); } /** * Quick and bulk edit saving. * * @param int $post_id * @param WP_Post $post * @return int */ public function bulk_and_quick_edit_save_post( $post_id, $post ) { // If this is an autosave, our form has not been submitted, so we don't want to do anything. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return $post_id; } // Don't save revisions and autosaves if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { return $post_id; } // Check post type is product if ( 'product' != $post->post_type ) { return $post_id; } // Check user permission if ( ! current_user_can( 'edit_post', $post_id ) ) { return $post_id; } // Check nonces if ( ! isset( $_REQUEST['woocommerce_quick_edit_nonce'] ) && ! isset( $_REQUEST['woocommerce_bulk_edit_nonce'] ) ) { return $post_id; } if ( isset( $_REQUEST['woocommerce_quick_edit_nonce'] ) && ! wp_verify_nonce( $_REQUEST['woocommerce_quick_edit_nonce'], 'woocommerce_quick_edit_nonce' ) ) { return $post_id; } if ( isset( $_REQUEST['woocommerce_bulk_edit_nonce'] ) && ! wp_verify_nonce( $_REQUEST['woocommerce_bulk_edit_nonce'], 'woocommerce_bulk_edit_nonce' ) ) { return $post_id; } // Get the product and save $product = wc_get_product( $post ); if ( ! empty( $_REQUEST['woocommerce_quick_edit'] ) ) { $this->quick_edit_save( $post_id, $product ); } else { $this->bulk_edit_save( $post_id, $product ); } // Clear transient wc_delete_product_transients( $post_id ); return $post_id; } /** * Quick edit. * * @param integer $post_id * @param WC_Product $product */ private function quick_edit_save( $post_id, $product ) { global $wpdb; $old_regular_price = $product->regular_price; $old_sale_price = $product->sale_price; // Save fields if ( isset( $_REQUEST['_sku'] ) ) { $sku = get_post_meta( $post_id, '_sku', true ); $new_sku = (string) wc_clean( $_REQUEST['_sku'] ); if ( $new_sku !== $sku ) { if ( ! empty( $new_sku ) ) { $unique_sku = wc_product_has_unique_sku( $post_id, $new_sku ); if ( $unique_sku ) { update_post_meta( $post_id, '_sku', $new_sku ); } } else { update_post_meta( $post_id, '_sku', '' ); } } } if ( isset( $_REQUEST['_weight'] ) ) { update_post_meta( $post_id, '_weight', wc_clean( $_REQUEST['_weight'] ) ); } if ( isset( $_REQUEST['_length'] ) ) { update_post_meta( $post_id, '_length', wc_clean( $_REQUEST['_length'] ) ); } if ( isset( $_REQUEST['_width'] ) ) { update_post_meta( $post_id, '_width', wc_clean( $_REQUEST['_width'] ) ); } if ( isset( $_REQUEST['_height'] ) ) { update_post_meta( $post_id, '_height', wc_clean( $_REQUEST['_height'] ) ); } if ( ! empty( $_REQUEST['_shipping_class'] ) ) { $shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] ); wp_set_object_terms( $post_id, $shipping_class, 'product_shipping_class' ); } if ( isset( $_REQUEST['_visibility'] ) ) { if ( update_post_meta( $post_id, '_visibility', wc_clean( $_REQUEST['_visibility'] ) ) ) { do_action( 'woocommerce_product_set_visibility', $post_id, wc_clean( $_REQUEST['_visibility'] ) ); } } if ( isset( $_REQUEST['_featured'] ) ) { if ( update_post_meta( $post_id, '_featured', 'yes' ) ) { delete_transient( 'wc_featured_products' ); } } else { if ( update_post_meta( $post_id, '_featured', 'no' ) ) { delete_transient( 'wc_featured_products' ); } } if ( isset( $_REQUEST['_tax_status'] ) ) { update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) ); } if ( isset( $_REQUEST['_tax_class'] ) ) { update_post_meta( $post_id, '_tax_class', wc_clean( $_REQUEST['_tax_class'] ) ); } if ( $product->is_type( 'simple' ) || $product->is_type( 'external' ) ) { if ( isset( $_REQUEST['_regular_price'] ) ) { $new_regular_price = ( '' === $_REQUEST['_regular_price'] ) ? '' : wc_format_decimal( $_REQUEST['_regular_price'] ); update_post_meta( $post_id, '_regular_price', $new_regular_price ); } else { $new_regular_price = null; } if ( isset( $_REQUEST['_sale_price'] ) ) { $new_sale_price = ( '' === $_REQUEST['_sale_price'] ) ? '' : wc_format_decimal( $_REQUEST['_sale_price'] ); update_post_meta( $post_id, '_sale_price', $new_sale_price ); } else { $new_sale_price = null; } // Handle price - remove dates and set to lowest $price_changed = false; if ( ! is_null( $new_regular_price ) && $new_regular_price != $old_regular_price ) { $price_changed = true; } elseif ( ! is_null( $new_sale_price ) && $new_sale_price != $old_sale_price ) { $price_changed = true; } if ( $price_changed ) { update_post_meta( $post_id, '_sale_price_dates_from', '' ); update_post_meta( $post_id, '_sale_price_dates_to', '' ); if ( ! is_null( $new_sale_price ) && '' !== $new_sale_price ) { update_post_meta( $post_id, '_price', $new_sale_price ); } else { update_post_meta( $post_id, '_price', $new_regular_price ); } } } // Handle Stock Data $manage_stock = ! empty( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->product_type ? 'yes' : 'no'; $backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : 'no'; $stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : 'instock'; $stock_amount = 'yes' === $manage_stock ? wc_stock_amount( $_REQUEST['_stock'] ) : ''; if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) { // Apply product type constraints to stock status if ( 'external' === $product->product_type ) { // External always in stock $stock_status = 'instock'; } elseif ( 'variable' === $product->product_type ) { // Stock status is always determined by children foreach ( $product->get_children() as $child_id ) { if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) { wc_update_product_stock_status( $child_id, $stock_status ); } } WC_Product_Variable::sync_stock_status( $post_id ); } update_post_meta( $post_id, '_manage_stock', $manage_stock ); update_post_meta( $post_id, '_backorders', $backorders ); if ( 'variable' !== $product->product_type ) { wc_update_product_stock_status( $post_id, $stock_status ); } wc_update_product_stock( $post_id, $stock_amount ); } else { wc_update_product_stock_status( $post_id, $stock_status ); } do_action( 'woocommerce_product_quick_edit_save', $product ); } /** * Bulk edit. * @param integer $post_id * @param WC_Product $product */ public function bulk_edit_save( $post_id, $product ) { $old_regular_price = $product->regular_price; $old_sale_price = $product->sale_price; // Save fields if ( ! empty( $_REQUEST['change_weight'] ) && isset( $_REQUEST['_weight'] ) ) { update_post_meta( $post_id, '_weight', wc_clean( stripslashes( $_REQUEST['_weight'] ) ) ); } if ( ! empty( $_REQUEST['change_dimensions'] ) ) { if ( isset( $_REQUEST['_length'] ) ) { update_post_meta( $post_id, '_length', wc_clean( stripslashes( $_REQUEST['_length'] ) ) ); } if ( isset( $_REQUEST['_width'] ) ) { update_post_meta( $post_id, '_width', wc_clean( stripslashes( $_REQUEST['_width'] ) ) ); } if ( isset( $_REQUEST['_height'] ) ) { update_post_meta( $post_id, '_height', wc_clean( stripslashes( $_REQUEST['_height'] ) ) ); } } if ( ! empty( $_REQUEST['_tax_status'] ) ) { update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) ); } if ( ! empty( $_REQUEST['_tax_class'] ) ) { $tax_class = wc_clean( $_REQUEST['_tax_class'] ); if ( 'standard' == $tax_class ) { $tax_class = ''; } update_post_meta( $post_id, '_tax_class', $tax_class ); } if ( ! empty( $_REQUEST['_shipping_class'] ) ) { $shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] ); wp_set_object_terms( $post_id, $shipping_class, 'product_shipping_class' ); } if ( ! empty( $_REQUEST['_visibility'] ) ) { if ( update_post_meta( $post_id, '_visibility', wc_clean( $_REQUEST['_visibility'] ) ) ) { do_action( 'woocommerce_product_set_visibility', $post_id, wc_clean( $_REQUEST['_visibility'] ) ); } } if ( ! empty( $_REQUEST['_featured'] ) ) { if ( update_post_meta( $post_id, '_featured', stripslashes( $_REQUEST['_featured'] ) ) ) { delete_transient( 'wc_featured_products' ); } } // Sold Individually if ( ! empty( $_REQUEST['_sold_individually'] ) ) { if ( 'yes' === $_REQUEST['_sold_individually'] ) { update_post_meta( $post_id, '_sold_individually', 'yes' ); } else { update_post_meta( $post_id, '_sold_individually', '' ); } } // Handle price - remove dates and set to lowest $change_price_product_types = apply_filters( 'woocommerce_bulk_edit_save_price_product_types', array( 'simple', 'external' ) ); $can_product_type_change_price = false; foreach ( $change_price_product_types as $product_type ) { if ( $product->is_type( $product_type ) ) { $can_product_type_change_price = true; break; } } if ( $can_product_type_change_price ) { $price_changed = false; if ( ! empty( $_REQUEST['change_regular_price'] ) ) { $change_regular_price = absint( $_REQUEST['change_regular_price'] ); $regular_price = esc_attr( stripslashes( $_REQUEST['_regular_price'] ) ); switch ( $change_regular_price ) { case 1 : $new_price = $regular_price; break; case 2 : if ( strstr( $regular_price, '%' ) ) { $percent = str_replace( '%', '', $regular_price ) / 100; $new_price = $old_regular_price + ( round( $old_regular_price * $percent, wc_get_price_decimals() ) ); } else { $new_price = $old_regular_price + $regular_price; } break; case 3 : if ( strstr( $regular_price, '%' ) ) { $percent = str_replace( '%', '', $regular_price ) / 100; $new_price = max( 0, $old_regular_price - ( round( $old_regular_price * $percent, wc_get_price_decimals() ) ) ); } else { $new_price = max( 0, $old_regular_price - $regular_price ); } break; default : break; } if ( isset( $new_price ) && $new_price != $old_regular_price ) { $price_changed = true; $new_price = round( $new_price, wc_get_price_decimals() ); update_post_meta( $post_id, '_regular_price', $new_price ); $product->regular_price = $new_price; } } if ( ! empty( $_REQUEST['change_sale_price'] ) ) { $change_sale_price = absint( $_REQUEST['change_sale_price'] ); $sale_price = esc_attr( stripslashes( $_REQUEST['_sale_price'] ) ); switch ( $change_sale_price ) { case 1 : $new_price = $sale_price; break; case 2 : if ( strstr( $sale_price, '%' ) ) { $percent = str_replace( '%', '', $sale_price ) / 100; $new_price = $old_sale_price + ( $old_sale_price * $percent ); } else { $new_price = $old_sale_price + $sale_price; } break; case 3 : if ( strstr( $sale_price, '%' ) ) { $percent = str_replace( '%', '', $sale_price ) / 100; $new_price = max( 0, $old_sale_price - ( $old_sale_price * $percent ) ); } else { $new_price = max( 0, $old_sale_price - $sale_price ); } break; case 4 : if ( strstr( $sale_price, '%' ) ) { $percent = str_replace( '%', '', $sale_price ) / 100; $new_price = max( 0, $product->regular_price - ( $product->regular_price * $percent ) ); } else { $new_price = max( 0, $product->regular_price - $sale_price ); } break; default : break; } if ( isset( $new_price ) && $new_price != $old_sale_price ) { $price_changed = true; $new_price = ! empty( $new_price ) || '0' === $new_price ? round( $new_price, wc_get_price_decimals() ) : ''; update_post_meta( $post_id, '_sale_price', $new_price ); $product->sale_price = $new_price; } } if ( $price_changed ) { update_post_meta( $post_id, '_sale_price_dates_from', '' ); update_post_meta( $post_id, '_sale_price_dates_to', '' ); if ( $product->regular_price < $product->sale_price ) { $product->sale_price = ''; update_post_meta( $post_id, '_sale_price', '' ); } if ( $product->sale_price ) { update_post_meta( $post_id, '_price', $product->sale_price ); } else { update_post_meta( $post_id, '_price', $product->regular_price ); } } } // Handle Stock Data $was_managing_stock = get_post_meta( $post_id, '_manage_stock', true ); $stock_status = get_post_meta( $post_id, '_stock_status', true ); $backorders = get_post_meta( $post_id, '_stock_status', true ); $backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : $backorders; $stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : $stock_status; if ( ! empty( $_REQUEST['_manage_stock'] ) ) { $manage_stock = 'yes' === wc_clean( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->product_type ? 'yes' : 'no'; } else { $manage_stock = $was_managing_stock; } $stock_amount = 'yes' === $manage_stock && isset( $_REQUEST['_change_stock'] ) ? wc_stock_amount( $_REQUEST['_change_stock'] ) : ''; if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) { // Apply product type constraints to stock status if ( 'external' === $product->product_type ) { // External always in stock $stock_status = 'instock'; } elseif ( 'variable' === $product->product_type ) { // Stock status is always determined by children foreach ( $product->get_children() as $child_id ) { if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) { wc_update_product_stock_status( $child_id, $stock_status ); } } WC_Product_Variable::sync_stock_status( $post_id ); } update_post_meta( $post_id, '_manage_stock', $manage_stock ); update_post_meta( $post_id, '_backorders', $backorders ); if ( 'variable' !== $product->product_type ) { wc_update_product_stock_status( $post_id, $stock_status ); } wc_update_product_stock( $post_id, $stock_amount ); } else { wc_update_product_stock_status( $post_id, $stock_status ); } do_action( 'woocommerce_product_bulk_edit_save', $product ); } /** * Add extra bulk action options to mark orders as complete or processing. * * Using Javascript until WordPress core fixes: https://core.trac.wordpress.org/ticket/16031. */ public function bulk_admin_footer() { global $post_type; if ( 'shop_order' == $post_type ) { ?> current_action(); // Bail out if this is not a status-changing action if ( strpos( $action, 'mark_' ) === false ) { return; } $order_statuses = wc_get_order_statuses(); $new_status = substr( $action, 5 ); // get the status name from action $report_action = 'marked_' . $new_status; // Sanity check: bail out if this is actually not a status, or is // not a registered status if ( ! isset( $order_statuses[ 'wc-' . $new_status ] ) ) { return; } $changed = 0; $post_ids = array_map( 'absint', (array) $_REQUEST['post'] ); foreach ( $post_ids as $post_id ) { $order = wc_get_order( $post_id ); $order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ), true ); do_action( 'woocommerce_order_edit_status', $post_id, $new_status ); $changed++; } $sendback = add_query_arg( array( 'post_type' => 'shop_order', $report_action => true, 'changed' => $changed, 'ids' => join( ',', $post_ids ) ), '' ); if ( isset( $_GET['post_status'] ) ) { $sendback = add_query_arg( 'post_status', sanitize_text_field( $_GET['post_status'] ), $sendback ); } wp_redirect( esc_url_raw( $sendback ) ); exit(); } /** * Show confirmation message that order status changed for number of orders. */ public function bulk_admin_notices() { global $post_type, $pagenow; // Bail out if not on shop order list page if ( 'edit.php' !== $pagenow || 'shop_order' !== $post_type ) { return; } $order_statuses = wc_get_order_statuses(); // Check if any status changes happened foreach ( $order_statuses as $slug => $name ) { if ( isset( $_REQUEST[ 'marked_' . str_replace( 'wc-', '', $slug ) ] ) ) { $number = isset( $_REQUEST['changed'] ) ? absint( $_REQUEST['changed'] ) : 0; /* translators: %s: orders count */ $message = sprintf( _n( 'Order status changed.', '%s order statuses changed.', $number, 'woocommerce' ), number_format_i18n( $number ) ); echo '

' . $message . '

'; break; } } } /** * Search custom fields as well as content. * @param WP_Query $wp */ public function shop_order_search_custom_fields( $wp ) { global $pagenow; if ( 'edit.php' != $pagenow || empty( $wp->query_vars['s'] ) || 'shop_order' !== $wp->query_vars['post_type'] ) { return; } $post_ids = wc_order_search( $_GET['s'] ); if ( ! empty( $post_ids ) ) { // Remove "s" - we don't want to search order name. unset( $wp->query_vars['s'] ); // so we know we're doing this. $wp->query_vars['shop_order_search'] = true; // Search by found posts. $wp->query_vars['post__in'] = array_merge( $post_ids, array( 0 ) ); } } /** * Change the label when searching orders. * * @param mixed $query * @return string */ public function shop_order_search_label( $query ) { global $pagenow, $typenow; if ( 'edit.php' != $pagenow ) { return $query; } if ( 'shop_order' !== $typenow ) { return $query; } if ( ! get_query_var( 'shop_order_search' ) ) { return $query; } return wp_unslash( $_GET['s'] ); } /** * Query vars for custom searches. * * @param mixed $public_query_vars * @return array */ public function add_custom_query_var( $public_query_vars ) { $public_query_vars[] = 'sku'; $public_query_vars[] = 'shop_order_search'; return $public_query_vars; } /** * Filters for post types. */ public function restrict_manage_posts() { global $typenow; if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ) ) ) { $this->shop_order_filters(); } elseif ( 'product' == $typenow ) { $this->product_filters(); } elseif ( 'shop_coupon' == $typenow ) { $this->shop_coupon_filters(); } } /** * Show a category filter box. */ public function product_filters() { global $wp_query; // Category Filtering wc_product_dropdown_categories(); // Type filtering $terms = get_terms( 'product_type' ); $output = ''; echo apply_filters( 'woocommerce_product_filters', $output ); } /** * Show custom filters to filter coupons by type. */ public function shop_coupon_filters() { ?> display_name, absint( $user->ID ), $user->user_email ); } ?> '_price', 'orderby' => 'meta_value_num', ) ); } if ( 'featured' == $vars['orderby'] ) { $vars = array_merge( $vars, array( 'meta_key' => '_featured', 'orderby' => 'meta_value', ) ); } if ( 'sku' == $vars['orderby'] ) { $vars = array_merge( $vars, array( 'meta_key' => '_sku', 'orderby' => 'meta_value', ) ); } } } elseif ( 'shop_coupon' === $typenow ) { if ( ! empty( $_GET['coupon_type'] ) ) { $vars['meta_key'] = 'discount_type'; $vars['meta_value'] = wc_clean( $_GET['coupon_type'] ); } } elseif ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ) ) ) { // Filter the orders by the posted customer. if ( isset( $_GET['_customer_user'] ) && $_GET['_customer_user'] > 0 ) { $vars['meta_query'] = array( array( 'key' => '_customer_user', 'value' => (int) $_GET['_customer_user'], 'compare' => '=', ), ); } // Sorting if ( isset( $vars['orderby'] ) ) { if ( 'order_total' == $vars['orderby'] ) { $vars = array_merge( $vars, array( 'meta_key' => '_order_total', 'orderby' => 'meta_value_num', ) ); } } // Status if ( ! isset( $vars['post_status'] ) ) { $post_statuses = wc_get_order_statuses(); foreach ( $post_statuses as $status => $value ) { if ( isset( $wp_post_statuses[ $status ] ) && false === $wp_post_statuses[ $status ]->show_in_admin_all_list ) { unset( $post_statuses[ $status ] ); } } $vars['post_status'] = array_keys( $post_statuses ); } } return $vars; } /** * Filter the products in admin based on options. * * @param mixed $query */ public function product_filters_query( $query ) { global $typenow, $wp_query; if ( 'product' == $typenow ) { if ( isset( $query->query_vars['product_type'] ) ) { // Subtypes if ( 'downloadable' == $query->query_vars['product_type'] ) { $query->query_vars['product_type'] = ''; $query->is_tax = false; $query->query_vars['meta_value'] = 'yes'; $query->query_vars['meta_key'] = '_downloadable'; } elseif ( 'virtual' == $query->query_vars['product_type'] ) { $query->query_vars['product_type'] = ''; $query->is_tax = false; $query->query_vars['meta_value'] = 'yes'; $query->query_vars['meta_key'] = '_virtual'; } } // Categories if ( isset( $_GET['product_cat'] ) && '0' === $_GET['product_cat'] ) { $query->query_vars['tax_query'][] = array( 'taxonomy' => 'product_cat', 'field' => 'id', 'terms' => get_terms( 'product_cat', array( 'fields' => 'ids' ) ), 'operator' => 'NOT IN', ); } // Shipping classes if ( isset( $_GET['product_shipping_class'] ) && '0' === $_GET['product_shipping_class'] ) { $query->query_vars['tax_query'][] = array( 'taxonomy' => 'product_shipping_class', 'field' => 'id', 'terms' => get_terms( 'product_shipping_class', array( 'fields' => 'ids' ) ), 'operator' => 'NOT IN', ); } } } /** * Search by SKU or ID for products. * * @param string $where * @return string */ public function product_search( $where ) { global $pagenow, $wpdb, $wp; if ( 'edit.php' != $pagenow || ! is_search() || ! isset( $wp->query_vars['s'] ) || 'product' != $wp->query_vars['post_type'] ) { return $where; } $search_ids = array(); $terms = explode( ',', $wp->query_vars['s'] ); foreach ( $terms as $term ) { if ( is_numeric( $term ) ) { $search_ids[] = $term; } // Attempt to get a SKU $sku_to_id = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_parent FROM {$wpdb->posts} LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id WHERE meta_key='_sku' AND meta_value LIKE %s;", '%' . $wpdb->esc_like( wc_clean( $term ) ) . '%' ) ); $sku_to_id = array_merge( wp_list_pluck( $sku_to_id, 'ID' ), wp_list_pluck( $sku_to_id, 'post_parent' ) ); if ( sizeof( $sku_to_id ) > 0 ) { $search_ids = array_merge( $search_ids, $sku_to_id ); } } $search_ids = array_filter( array_unique( array_map( 'absint', $search_ids ) ) ); if ( sizeof( $search_ids ) > 0 ) { $where = str_replace( 'AND (((', "AND ( ({$wpdb->posts}.ID IN (" . implode( ',', $search_ids ) . ")) OR ((", $where ); } return $where; } /** * Disable the auto-save functionality for Orders. */ public function disable_autosave() { global $post; if ( $post && in_array( get_post_type( $post->ID ), wc_get_order_types( 'order-meta-boxes' ) ) ) { wp_dequeue_script( 'autosave' ); } } /** * Removes variations etc belonging to a deleted post, and clears transients. * * @param mixed $id ID of post being deleted */ public function delete_post( $id ) { global $woocommerce, $wpdb; if ( ! current_user_can( 'delete_posts' ) ) { return; } if ( $id > 0 ) { $post_type = get_post_type( $id ); switch ( $post_type ) { case 'product' : $child_product_variations = get_children( 'post_parent=' . $id . '&post_type=product_variation' ); if ( ! empty( $child_product_variations ) ) { foreach ( $child_product_variations as $child ) { wp_delete_post( $child->ID, true ); } } $child_products = get_children( 'post_parent=' . $id . '&post_type=product' ); if ( ! empty( $child_products ) ) { foreach ( $child_products as $child ) { $child_post = array(); $child_post['ID'] = $child->ID; $child_post['post_parent'] = 0; wp_update_post( $child_post ); } } if ( $parent_id = wp_get_post_parent_id( $id ) ) { wc_delete_product_transients( $parent_id ); } break; case 'product_variation' : wc_delete_product_transients( wp_get_post_parent_id( $id ) ); break; case 'shop_order' : $refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) ); if ( ! is_null( $refunds ) ) { foreach ( $refunds as $refund ) { wp_delete_post( $refund->ID, true ); } } break; } } } /** * woocommerce_trash_post function. * * @param mixed $id */ public function trash_post( $id ) { global $wpdb; if ( $id > 0 ) { $post_type = get_post_type( $id ); if ( in_array( $post_type, wc_get_order_types( 'order-count' ) ) ) { // Delete count - meta doesn't work on trashed posts $user_id = get_post_meta( $id, '_customer_user', true ); if ( $user_id > 0 ) { delete_user_meta( $user_id, '_money_spent' ); delete_user_meta( $user_id, '_order_count' ); } $refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) ); foreach ( $refunds as $refund ) { $wpdb->update( $wpdb->posts, array( 'post_status' => 'trash' ), array( 'ID' => $refund->ID ) ); } delete_transient( 'woocommerce_processing_order_count' ); wc_delete_shop_order_transients( $id ); } } } /** * woocommerce_untrash_post function. * * @param mixed $id */ public function untrash_post( $id ) { global $wpdb; if ( $id > 0 ) { $post_type = get_post_type( $id ); if ( in_array( $post_type, wc_get_order_types( 'order-count' ) ) ) { // Delete count - meta doesn't work on trashed posts $user_id = get_post_meta( $id, '_customer_user', true ); if ( $user_id > 0 ) { delete_user_meta( $user_id, '_money_spent' ); delete_user_meta( $user_id, '_order_count' ); } $refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) ); foreach ( $refunds as $refund ) { $wpdb->update( $wpdb->posts, array( 'post_status' => 'wc-completed' ), array( 'ID' => $refund->ID ) ); } delete_transient( 'woocommerce_processing_order_count' ); wc_delete_shop_order_transients( $id ); } elseif ( 'product' === $post_type ) { // Check if SKU is valid before untrash the product. $sku = get_post_meta( $id, '_sku', true ); if ( ! empty( $sku ) ) { if ( ! wc_product_has_unique_sku( $id, $sku ) ) { update_post_meta( $id, '_sku', '' ); } } } } } /** * Remove item meta on permanent deletion. */ public function delete_order_items( $postid ) { global $wpdb; if ( in_array( get_post_type( $postid ), wc_get_order_types() ) ) { do_action( 'woocommerce_delete_order_items', $postid ); $wpdb->query( " DELETE {$wpdb->prefix}woocommerce_order_items, {$wpdb->prefix}woocommerce_order_itemmeta FROM {$wpdb->prefix}woocommerce_order_items JOIN {$wpdb->prefix}woocommerce_order_itemmeta ON {$wpdb->prefix}woocommerce_order_items.order_item_id = {$wpdb->prefix}woocommerce_order_itemmeta.order_item_id WHERE {$wpdb->prefix}woocommerce_order_items.order_id = '{$postid}'; " ); do_action( 'woocommerce_deleted_order_items', $postid ); } } /** * Remove downloadable permissions on permanent order deletion. */ public function delete_order_downloadable_permissions( $postid ) { global $wpdb; if ( in_array( get_post_type( $postid ), wc_get_order_types() ) ) { do_action( 'woocommerce_delete_order_downloadable_permissions', $postid ); $wpdb->query( $wpdb->prepare( " DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d ", $postid ) ); do_action( 'woocommerce_deleted_order_downloadable_permissions', $postid ); } } /** * Change title boxes in admin. * @param string $text * @param object $post * @return string */ public function enter_title_here( $text, $post ) { switch ( $post->post_type ) { case 'product' : $text = __( 'Product name', 'woocommerce' ); break; case 'shop_coupon' : $text = __( 'Coupon code', 'woocommerce' ); break; } return $text; } /** * Print coupon description textarea field. * @param WP_Post $post */ public function edit_form_after_title( $post ) { if ( 'shop_coupon' === $post->post_type ) { ?> post_type && 'post' === $screen->base ) { $hidden = array_merge( $hidden, array( 'postcustom' ) ); } return $hidden; } /** * Output product visibility options. */ public function product_data_visibility() { global $post; if ( 'product' != $post->post_type ) { return; } $current_visibility = ( $current_visibility = get_post_meta( $post->ID, '_visibility', true ) ) ? $current_visibility : apply_filters( 'woocommerce_product_visibility_default' , 'visible' ); $current_featured = ( $current_featured = get_post_meta( $post->ID, '_featured', true ) ) ? $current_featured : 'no'; $visibility_options = apply_filters( 'woocommerce_product_visibility_options', array( 'visible' => __( 'Catalog/search', 'woocommerce' ), 'catalog' => __( 'Catalog', 'woocommerce' ), 'search' => __( 'Search', 'woocommerce' ), 'hidden' => __( 'Hidden', 'woocommerce' ), ) ); ?>
' . __( 'Choose where this product should be displayed in your catalog. The product will always be accessible directly.', 'woocommerce' ) . '

'; foreach ( $visibility_options as $name => $label ) { echo '
'; } echo '

' . __( 'Enable this option to feature this product.', 'woocommerce' ) . '

'; echo '
'; ?>

get_files() ); $updated_download_ids = array_keys( (array) $downloadable_files ); $new_download_ids = array_filter( array_diff( $updated_download_ids, $existing_download_ids ) ); $removed_download_ids = array_filter( array_diff( $existing_download_ids, $updated_download_ids ) ); if ( ! empty( $new_download_ids ) || ! empty( $removed_download_ids ) ) { // determine whether downloadable file access has been granted via the typical order completion, or via the admin ajax method $existing_permissions = $wpdb->get_results( $wpdb->prepare( "SELECT * from {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE product_id = %d GROUP BY order_id", $product_id ) ); foreach ( $existing_permissions as $existing_permission ) { $order = wc_get_order( $existing_permission->order_id ); if ( $order->get_id() ) { // Remove permissions if ( ! empty( $removed_download_ids ) ) { foreach ( $removed_download_ids as $download_id ) { if ( apply_filters( 'woocommerce_process_product_file_download_paths_remove_access_to_old_file', true, $download_id, $product_id, $order ) ) { $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d AND product_id = %d AND download_id = %s", $order->get_id(), $product_id, $download_id ) ); } } } // Add permissions if ( ! empty( $new_download_ids ) ) { foreach ( $new_download_ids as $download_id ) { if ( apply_filters( 'woocommerce_process_product_file_download_paths_grant_access_to_new_file', true, $download_id, $product_id, $order ) ) { // grant permission if it doesn't already exist if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT 1=1 FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d AND product_id = %d AND download_id = %s", $order->get_id(), $product_id, $download_id ) ) ) { wc_downloadable_file_permission( $download_id, $product_id, $order ); } } } } } } } } /** * Disable DFW feature pointer. */ public function disable_dfw_feature_pointer() { $screen = get_current_screen(); if ( $screen && 'product' === $screen->id && 'post' === $screen->base ) { remove_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_wp410_dfw' ) ); } } /** * Removes products, orders, and coupons from the list of post types that support "View Mode" switching. * View mode is seen on posts where you can switch between list or excerpt. Our post types don't support * it, so we want to hide the useless UI from the screen options tab. * * @since 2.6 * @param array $post_types Array of post types supporting view mode * @return array Array of post types supporting view mode, without products, orders, and coupons */ public function disable_view_mode_options( $post_types ) { unset( $post_types['product'], $post_types['shop_order'], $post_types['shop_coupon'] ); return $post_types; } /** * Show blank slate. */ public function maybe_render_blank_state( $which ) { global $post_type; if ( in_array( $post_type, array( 'shop_order', 'product', 'shop_coupon' ) ) && 'bottom' === $which ) { $counts = (array) wp_count_posts( $post_type ); unset( $counts['auto-draft'] ); $count = array_sum( $counts ); if ( 0 < $count ) { return; } echo '
'; switch ( $post_type ) { case 'shop_order' : ?>

#posts-filter .wp-list-table, #posts-filter .tablenav.top, .wrap .subsubsub { display: none; }
'; } } /** * When editing the shop page, we should hide templates. * @return array */ public function hide_cpt_archive_templates( $page_templates, $class, $post ) { $shop_page_id = wc_get_page_id( 'shop' ); if ( $post && absint( $shop_page_id ) === absint( $post->ID ) ) { $page_templates = array(); } return $page_templates; } /** * Show a notice above the CPT archive. */ public function show_cpt_archive_notice( $post ) { $shop_page_id = wc_get_page_id( 'shop' ); if ( $post && absint( $shop_page_id ) === absint( $post->ID ) ) { ?>

You can read more about this here.', 'woocommerce' ), 'https://docs.woocommerce.com/document/woocommerce-pages/#section-4' ); ?>

get_quantity() ); ?> get_sku() ) ? $product->get_sku() . ' - ' : ''; ?>get_name(), $item, false ); ?> get_name(), $item, false ); ?>