PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/admin/post-types/product.php

https://github.com/CammoKing/woocommerce
PHP | 1199 lines | 839 code | 193 blank | 167 comment | 214 complexity | 466cbd11b174c676927a5640b476b3e4 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * Admin functions for the shop_product post type
  4. *
  5. * @author WooThemes
  6. * @category Admin
  7. * @package WooCommerce/Admin/Products
  8. * @version 1.6.4
  9. */
  10. if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
  11. /**
  12. * Duplicate a product link on products list
  13. *
  14. * @access public
  15. * @param mixed $actions
  16. * @param mixed $post
  17. * @return array
  18. */
  19. function woocommerce_duplicate_product_link_row($actions, $post) {
  20. if ( function_exists( 'duplicate_post_plugin_activation' ) )
  21. return $actions;
  22. if ( ! current_user_can( 'manage_woocommerce' ) ) return $actions;
  23. if ( $post->post_type != 'product' )
  24. return $actions;
  25. $actions['duplicate'] = '<a href="' . wp_nonce_url( admin_url( 'admin.php?action=duplicate_product&amp;post=' . $post->ID ), 'woocommerce-duplicate-product_' . $post->ID ) . '" title="' . __( 'Make a duplicate from this product', 'woocommerce' )
  26. . '" rel="permalink">' . __( 'Duplicate', 'woocommerce' ) . '</a>';
  27. return $actions;
  28. }
  29. add_filter( 'post_row_actions', 'woocommerce_duplicate_product_link_row',10,2 );
  30. add_filter( 'page_row_actions', 'woocommerce_duplicate_product_link_row',10,2 );
  31. /**
  32. * Duplicate a product link on edit screen
  33. *
  34. * @access public
  35. * @return void
  36. */
  37. function woocommerce_duplicate_product_post_button() {
  38. global $post;
  39. if ( function_exists( 'duplicate_post_plugin_activation' ) ) return;
  40. if ( ! current_user_can( 'manage_woocommerce' ) ) return;
  41. if ( ! is_object( $post ) ) return;
  42. if ( $post->post_type != 'product' ) return;
  43. if ( isset( $_GET['post'] ) ) {
  44. $notifyUrl = wp_nonce_url( admin_url( "admin.php?action=duplicate_product&post=" . absint( $_GET['post'] ) ), 'woocommerce-duplicate-product_' . $_GET['post'] );
  45. ?>
  46. <div id="duplicate-action"><a class="submitduplicate duplication" href="<?php echo esc_url( $notifyUrl ); ?>"><?php _e( 'Copy to a new draft', 'woocommerce' ); ?></a></div>
  47. <?php
  48. }
  49. }
  50. add_action( 'post_submitbox_start', 'woocommerce_duplicate_product_post_button' );
  51. /**
  52. * Columns for Products page
  53. *
  54. * @access public
  55. * @param mixed $columns
  56. * @return array
  57. */
  58. function woocommerce_edit_product_columns( $columns ) {
  59. global $woocommerce;
  60. if ( empty( $columns ) && ! is_array( $columns ) )
  61. $columns = array();
  62. unset( $columns['title'], $columns['comments'], $columns['date'] );
  63. $columns["cb"] = "<input type=\"checkbox\" />";
  64. $columns["thumb"] = __( 'Image', 'woocommerce' );
  65. $columns["name"] = __( 'Name', 'woocommerce' );
  66. if (get_option('woocommerce_enable_sku', true) == 'yes')
  67. $columns["sku"] = __( 'SKU', 'woocommerce' );
  68. if (get_option('woocommerce_manage_stock')=='yes')
  69. $columns["is_in_stock"] = __( 'Stock', 'woocommerce' );
  70. $columns["price"] = __( 'Price', 'woocommerce' );
  71. $columns["product_cat"] = __( 'Categories', 'woocommerce' );
  72. $columns["product_tag"] = __( 'Tags', 'woocommerce' );
  73. $columns["featured"] = '<img src="' . $woocommerce->plugin_url() . '/assets/images/featured.png" alt="' . __( 'Featured', 'woocommerce' ) . '" class="tips" data-tip="' . __( 'Featured', 'woocommerce' ) . '" width="12" height="12" />';
  74. $columns["product_type"] = '<img src="' . $woocommerce->plugin_url() . '/assets/images/product_type_head.png" alt="' . __( 'Type', 'woocommerce' ) . '" class="tips" data-tip="' . __( 'Type', 'woocommerce' ) . '" width="14" height="12" />';
  75. $columns["date"] = __( 'Date', 'woocommerce' );
  76. return $columns;
  77. }
  78. add_filter('manage_edit-product_columns', 'woocommerce_edit_product_columns');
  79. /**
  80. * Custom Columns for Products page
  81. *
  82. * @access public
  83. * @param mixed $column
  84. * @return void
  85. */
  86. function woocommerce_custom_product_columns( $column ) {
  87. global $post, $woocommerce;
  88. $product = get_product($post);
  89. switch ($column) {
  90. case "thumb" :
  91. echo $product->get_image();
  92. break;
  93. case "name" :
  94. $edit_link = get_edit_post_link( $post->ID );
  95. $title = _draft_or_post_title();
  96. $post_type_object = get_post_type_object( $post->post_type );
  97. $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID );
  98. echo '<strong><a class="row-title" href="'.$edit_link.'">' . $title.'</a>';
  99. _post_states( $post );
  100. echo '</strong>';
  101. if ( $post->post_parent > 0 )
  102. echo '&nbsp;&nbsp;&larr; <a href="'. get_edit_post_link($post->post_parent) .'">'. get_the_title($post->post_parent) .'</a>';
  103. // Excerpt view
  104. if (isset($_GET['mode']) && $_GET['mode']=='excerpt') echo apply_filters('the_excerpt', $post->post_excerpt);
  105. // Get actions
  106. $actions = array();
  107. $actions['id'] = 'ID: ' . $post->ID;
  108. if ( $can_edit_post && 'trash' != $post->post_status ) {
  109. $actions['inline hide-if-no-js'] = '<a href="#" class="editinline" title="' . esc_attr( __( 'Edit this item inline', 'woocommerce' ) ) . '">' . __( 'Quick&nbsp;Edit', 'woocommerce' ) . '</a>';
  110. }
  111. if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) {
  112. if ( 'trash' == $post->post_status )
  113. $actions['untrash'] = "<a title='" . esc_attr( __( 'Restore this item from the Trash', 'woocommerce' ) ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-' . $post->post_type . '_' . $post->ID ) . "'>" . __( 'Restore', 'woocommerce' ) . "</a>";
  114. elseif ( EMPTY_TRASH_DAYS )
  115. $actions['trash'] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash', 'woocommerce' ) . "</a>";
  116. if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS )
  117. $actions['delete'] = "<a class='submitdelete' title='" . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID, '', true ) . "'>" . __( 'Delete Permanently', 'woocommerce' ) . "</a>";
  118. }
  119. if ( $post_type_object->public ) {
  120. if ( in_array( $post->post_status, array( 'pending', 'draft' ) ) ) {
  121. if ( $can_edit_post )
  122. $actions['view'] = '<a href="' . esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) . '" title="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'Preview', 'woocommerce' ) . '</a>';
  123. } elseif ( 'trash' != $post->post_status ) {
  124. $actions['view'] = '<a href="' . get_permalink( $post->ID ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'View', 'woocommerce' ) . '</a>';
  125. }
  126. }
  127. $actions = apply_filters( 'post_row_actions', $actions, $post );
  128. echo '<div class="row-actions">';
  129. $i = 0;
  130. $action_count = sizeof($actions);
  131. foreach ( $actions as $action => $link ) {
  132. ++$i;
  133. ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
  134. echo "<span class='$action'>$link$sep</span>";
  135. }
  136. echo '</div>';
  137. get_inline_data( $post );
  138. /* Custom inline data for woocommerce */
  139. echo '
  140. <div class="hidden" id="woocommerce_inline_' . $post->ID . '">
  141. <div class="menu_order">' . $post->menu_order . '</div>
  142. <div class="sku">' . $product->sku . '</div>
  143. <div class="regular_price">' . $product->regular_price . '</div>
  144. <div class="sale_price">' . $product->sale_price . '</div>
  145. <div class="weight">' . $product->weight . '</div>
  146. <div class="length">' . $product->length . '</div>
  147. <div class="width">' . $product->width . '</div>
  148. <div class="height">' . $product->height . '</div>
  149. <div class="visibility">' . $product->visibility . '</div>
  150. <div class="stock_status">' . $product->stock_status . '</div>
  151. <div class="stock">' . $product->stock . '</div>
  152. <div class="manage_stock">' . $product->manage_stock . '</div>
  153. <div class="featured">' . $product->featured . '</div>
  154. <div class="product_type">' . $product->product_type . '</div>
  155. <div class="product_is_virtual">' . $product->virtual . '</div>
  156. </div>
  157. ';
  158. break;
  159. case "sku" :
  160. if ($product->get_sku()) echo $product->get_sku(); else echo '<span class="na">&ndash;</span>';
  161. break;
  162. case "product_type" :
  163. if( $product->product_type == 'grouped' ):
  164. echo '<span class="product-type tips '.$product->product_type.'" data-tip="' . __( 'Grouped', 'woocommerce' ) . '"></span>';
  165. elseif ( $product->product_type == 'external' ):
  166. echo '<span class="product-type tips '.$product->product_type.'" data-tip="' . __( 'External/Affiliate', 'woocommerce' ) . '"></span>';
  167. elseif ( $product->product_type == 'simple' ):
  168. if ($product->is_virtual()) {
  169. echo '<span class="product-type tips virtual" data-tip="' . __( 'Virtual', 'woocommerce' ) . '"></span>';
  170. } elseif ($product->is_downloadable()) {
  171. echo '<span class="product-type tips downloadable" data-tip="' . __( 'Downloadable', 'woocommerce' ) . '"></span>';
  172. } else {
  173. echo '<span class="product-type tips '.$product->product_type.'" data-tip="' . __( 'Simple', 'woocommerce' ) . '"></span>';
  174. }
  175. elseif ( $product->product_type == 'variable' ):
  176. echo '<span class="product-type tips '.$product->product_type.'" data-tip="' . __( 'Variable', 'woocommerce' ) . '"></span>';
  177. else:
  178. // Assuming that we have other types in future
  179. echo '<span class="product-type tips '.$product->product_type.'" data-tip="' . ucwords($product->product_type) . '"></span>';
  180. endif;
  181. break;
  182. case "price":
  183. if ($product->get_price_html()) echo $product->get_price_html(); else echo '<span class="na">&ndash;</span>';
  184. break;
  185. case "product_cat" :
  186. case "product_tag" :
  187. if ( ! $terms = get_the_terms( $post->ID, $column ) ) {
  188. echo '<span class="na">&ndash;</span>';
  189. } else {
  190. foreach ( $terms as $term ) {
  191. $termlist[] = '<a href="' . admin_url( 'edit.php?' . $column . '=' . $term->slug . '&post_type=product' ) . ' ">' . $term->name . '</a>';
  192. }
  193. echo implode( ', ', $termlist );
  194. }
  195. break;
  196. case "featured" :
  197. $url = wp_nonce_url( admin_url('admin-ajax.php?action=woocommerce-feature-product&product_id=' . $post->ID), 'woocommerce-feature-product' );
  198. echo '<a href="'.$url.'" title="'.__( 'Change', 'woocommerce' ) .'">';
  199. if ($product->is_featured()) echo '<a href="'.$url.'"><img src="'.$woocommerce->plugin_url().'/assets/images/featured.png" alt="yes" height="14" width="14" />';
  200. else echo '<img src="'.$woocommerce->plugin_url().'/assets/images/featured-off.png" alt="no" height="14" width="14" />';
  201. echo '</a>';
  202. break;
  203. case "is_in_stock" :
  204. if ($product->is_in_stock()) {
  205. echo '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
  206. } else {
  207. echo '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
  208. }
  209. if ( $product->managing_stock() ) :
  210. echo ' &times; ' . $product->get_total_stock();
  211. endif;
  212. break;
  213. }
  214. }
  215. add_action('manage_product_posts_custom_column', 'woocommerce_custom_product_columns', 2 );
  216. /**
  217. * Make product columns sortable
  218. * https://gist.github.com/906872
  219. **/
  220. /**
  221. * Make product columns sortable
  222. *
  223. * https://gist.github.com/906872
  224. *
  225. * @access public
  226. * @param mixed $columns
  227. * @return array
  228. */
  229. function woocommerce_custom_product_sort($columns) {
  230. $custom = array(
  231. 'is_in_stock' => 'inventory',
  232. 'price' => 'price',
  233. 'featured' => 'featured',
  234. 'sku' => 'sku',
  235. 'name' => 'title'
  236. );
  237. return wp_parse_args( $custom, $columns );
  238. }
  239. add_filter( 'manage_edit-product_sortable_columns', 'woocommerce_custom_product_sort');
  240. /**
  241. * Product column orderby
  242. *
  243. * http://scribu.net/wordpress/custom-sortable-columns.html#comment-4732
  244. *
  245. * @access public
  246. * @param mixed $vars
  247. * @return array
  248. */
  249. function woocommerce_custom_product_orderby( $vars ) {
  250. if (isset( $vars['orderby'] )) :
  251. if ( 'inventory' == $vars['orderby'] ) :
  252. $vars = array_merge( $vars, array(
  253. 'meta_key' => '_stock',
  254. 'orderby' => 'meta_value_num'
  255. ) );
  256. endif;
  257. if ( 'price' == $vars['orderby'] ) :
  258. $vars = array_merge( $vars, array(
  259. 'meta_key' => '_price',
  260. 'orderby' => 'meta_value_num'
  261. ) );
  262. endif;
  263. if ( 'featured' == $vars['orderby'] ) :
  264. $vars = array_merge( $vars, array(
  265. 'meta_key' => '_featured',
  266. 'orderby' => 'meta_value'
  267. ) );
  268. endif;
  269. if ( 'sku' == $vars['orderby'] ) :
  270. $vars = array_merge( $vars, array(
  271. 'meta_key' => '_sku',
  272. 'orderby' => 'meta_value'
  273. ) );
  274. endif;
  275. endif;
  276. return $vars;
  277. }
  278. add_filter( 'request', 'woocommerce_custom_product_orderby' );
  279. /**
  280. * Filter products by category, uses slugs for option values.
  281. *
  282. * Code adapted by Andrew Benbow
  283. *
  284. * @access public
  285. * @return void
  286. */
  287. function woocommerce_products_by_category() {
  288. global $typenow, $wp_query;
  289. if ($typenow=='product') :
  290. woocommerce_product_dropdown_categories();
  291. endif;
  292. }
  293. add_action('restrict_manage_posts','woocommerce_products_by_category');
  294. /**
  295. * Filter products by type
  296. *
  297. * @access public
  298. * @return void
  299. */
  300. function woocommerce_products_by_type() {
  301. global $typenow, $wp_query;
  302. if ($typenow=='product') :
  303. // Types
  304. $terms = get_terms('product_type');
  305. $output = "<select name='product_type' id='dropdown_product_type'>";
  306. $output .= '<option value="">'.__( 'Show all product types', 'woocommerce' ).'</option>';
  307. foreach($terms as $term) :
  308. $output .="<option value='$term->slug' ";
  309. if ( isset( $wp_query->query['product_type'] ) ) $output .=selected($term->slug, $wp_query->query['product_type'], false);
  310. $output .=">";
  311. // Its was dynamic but did not support the translations
  312. if( $term->name == 'grouped' ):
  313. $output .= __( 'Grouped product', 'woocommerce' );
  314. elseif ( $term->name == 'external' ):
  315. $output .= __( 'External/Affiliate product', 'woocommerce' );
  316. elseif ( $term->name == 'simple' ):
  317. $output .= __( 'Simple product', 'woocommerce' );
  318. elseif ( $term->name == 'variable' ):
  319. $output .= __( 'Variable', 'woocommerce' );
  320. else:
  321. // Assuming that we have other types in future
  322. $output .= ucwords($term->name);
  323. endif;
  324. $output .=" ($term->count)</option>";
  325. endforeach;
  326. $output .="</select>";
  327. // Downloadable/virtual
  328. $output .= "<select name='product_subtype' id='dropdown_product_subtype'>";
  329. $output .= '<option value="">'.__( 'Show all sub-types', 'woocommerce' ).'</option>';
  330. $output .="<option value='downloadable' ";
  331. if ( isset( $_GET['product_subtype'] ) ) $output .= selected('downloadable', $_GET['product_subtype'], false);
  332. $output .=">".__( 'Downloadable', 'woocommerce' )."</option>";
  333. $output .="<option value='virtual' ";
  334. if ( isset( $_GET['product_subtype'] ) ) $output .= selected('virtual', $_GET['product_subtype'], false);
  335. $output .=">".__( 'Virtual', 'woocommerce' )."</option>";
  336. $output .="</select>";
  337. echo $output;
  338. endif;
  339. }
  340. add_action('restrict_manage_posts', 'woocommerce_products_by_type');
  341. /**
  342. * Filter the products in admin based on options
  343. *
  344. * @access public
  345. * @param mixed $query
  346. * @return void
  347. */
  348. function woocommerce_admin_product_filter_query( $query ) {
  349. global $typenow, $wp_query;
  350. if ( $typenow == 'product' ) {
  351. // Subtypes
  352. if ( ! empty( $_GET['product_subtype'] ) ) {
  353. if ( $_GET['product_subtype'] == 'downloadable' ) {
  354. $query->query_vars['meta_value'] = 'yes';
  355. $query->query_vars['meta_key'] = '_downloadable';
  356. } elseif ( $_GET['product_subtype'] == 'virtual' ) {
  357. $query->query_vars['meta_value'] = 'yes';
  358. $query->query_vars['meta_key'] = '_virtual';
  359. }
  360. }
  361. // Categories
  362. if ( isset( $_GET['product_cat'] ) && $_GET['product_cat'] == '0' ) {
  363. $query->query_vars['tax_query'][] = array(
  364. 'taxonomy' => 'product_cat',
  365. 'field' => 'id',
  366. 'terms' => get_terms( 'product_cat', array( 'fields' => 'ids' ) ),
  367. 'operator' => 'NOT IN'
  368. );
  369. }
  370. }
  371. }
  372. add_filter( 'parse_query', 'woocommerce_admin_product_filter_query' );
  373. /**
  374. * Search by SKU or ID for products. Adapted from code by BenIrvin (Admin Search by ID)
  375. *
  376. * @access public
  377. * @param mixed $wp
  378. * @return void
  379. */
  380. function woocommerce_admin_product_search( $wp ) {
  381. global $pagenow, $wpdb;
  382. if( 'edit.php' != $pagenow ) return;
  383. if( !isset( $wp->query_vars['s'] ) ) return;
  384. if ($wp->query_vars['post_type']!='product') return;
  385. if( '#' == substr( $wp->query_vars['s'], 0, 1 ) ) :
  386. $id = absint( substr( $wp->query_vars['s'], 1 ) );
  387. if( !$id ) return;
  388. unset( $wp->query_vars['s'] );
  389. $wp->query_vars['p'] = $id;
  390. elseif( 'SKU:' == substr( $wp->query_vars['s'], 0, 4 ) ) :
  391. $sku = trim( substr( $wp->query_vars['s'], 4 ) );
  392. if( !$sku ) return;
  393. $ids = $wpdb->get_col( 'SELECT post_id FROM ' . $wpdb->postmeta . ' WHERE meta_key="_sku" AND meta_value LIKE "%' . $sku . '%";' );
  394. if ( ! $ids ) return;
  395. unset( $wp->query_vars['s'] );
  396. $wp->query_vars['post__in'] = $ids;
  397. $wp->query_vars['sku'] = $sku;
  398. endif;
  399. }
  400. /**
  401. * Label for the search by ID/SKU feature
  402. *
  403. * @access public
  404. * @param mixed $query
  405. * @return void
  406. */
  407. function woocommerce_admin_product_search_label($query) {
  408. global $pagenow, $typenow, $wp;
  409. if ( 'edit.php' != $pagenow ) return $query;
  410. if ( $typenow!='product' ) return $query;
  411. $s = get_query_var( 's' );
  412. if ($s) return $query;
  413. $sku = get_query_var( 'sku' );
  414. if($sku) {
  415. $post_type = get_post_type_object($wp->query_vars['post_type']);
  416. return sprintf(__( '[%s with SKU of %s]', 'woocommerce' ), $post_type->labels->singular_name, $sku);
  417. }
  418. $p = get_query_var( 'p' );
  419. if ($p) {
  420. $post_type = get_post_type_object($wp->query_vars['post_type']);
  421. return sprintf(__( '[%s with ID of %d]', 'woocommerce' ), $post_type->labels->singular_name, $p);
  422. }
  423. return $query;
  424. }
  425. if ( is_admin() ) {
  426. add_action( 'parse_request', 'woocommerce_admin_product_search' );
  427. add_filter( 'get_search_query', 'woocommerce_admin_product_search_label' );
  428. }
  429. /**
  430. * Custom quick edit - form
  431. *
  432. * @access public
  433. * @param mixed $column_name
  434. * @param mixed $post_type
  435. * @return void
  436. */
  437. function woocommerce_admin_product_quick_edit( $column_name, $post_type ) {
  438. if ($column_name != 'price' || $post_type != 'product') return;
  439. ?>
  440. <fieldset class="inline-edit-col-left">
  441. <div id="woocommerce-fields" class="inline-edit-col">
  442. <h4><?php _e( 'Product Data', 'woocommerce' ); ?></h4>
  443. <?php if( get_option('woocommerce_enable_sku', true) !== 'no' ) : ?>
  444. <label>
  445. <span class="title"><?php _e( 'SKU', 'woocommerce' ); ?></span>
  446. <span class="input-text-wrap">
  447. <input type="text" name="_sku" class="text sku" value="">
  448. </span>
  449. </label>
  450. <br class="clear" />
  451. <?php endif; ?>
  452. <div class="price_fields">
  453. <label>
  454. <span class="title"><?php _e( 'Price', 'woocommerce' ); ?></span>
  455. <span class="input-text-wrap">
  456. <input type="text" name="_regular_price" class="text regular_price" placeholder="<?php _e( 'Regular price', 'woocommerce' ); ?>" value="">
  457. </span>
  458. </label>
  459. <br class="clear" />
  460. <label>
  461. <span class="title"><?php _e( 'Sale', 'woocommerce' ); ?></span>
  462. <span class="input-text-wrap">
  463. <input type="text" name="_sale_price" class="text sale_price" placeholder="<?php _e( 'Sale price', 'woocommerce' ); ?>" value="">
  464. </span>
  465. </label>
  466. <br class="clear" />
  467. </div>
  468. <?php if ( get_option('woocommerce_enable_weight') == "yes" || get_option('woocommerce_enable_dimensions') == "yes" ) : ?>
  469. <div class="dimension_fields">
  470. <?php if ( get_option('woocommerce_enable_weight') == "yes" ) : ?>
  471. <label>
  472. <span class="title"><?php _e( 'Weight', 'woocommerce' ); ?></span>
  473. <span class="input-text-wrap">
  474. <input type="text" name="_weight" class="text weight" placeholder="0.00" value="">
  475. </span>
  476. </label>
  477. <br class="clear" />
  478. <?php endif; ?>
  479. <?php if ( get_option('woocommerce_enable_dimensions') == "yes" ) : ?>
  480. <div class="inline-edit-group dimensions">
  481. <div>
  482. <span class="title"><?php _e( 'L/W/H', 'woocommerce' ); ?></span>
  483. <span class="input-text-wrap">
  484. <input type="text" name="_length" class="text length" placeholder="<?php _e( 'Length', 'woocommerce' ); ?>" value="">
  485. <input type="text" name="_width" class="text width" placeholder="<?php _e( 'Width', 'woocommerce' ); ?>" value="">
  486. <input type="text" name="_height" class="text height" placeholder="<?php _e( 'Height', 'woocommerce' ); ?>" value="">
  487. </span>
  488. </div>
  489. </div>
  490. <?php endif; ?>
  491. </div>
  492. <?php endif; ?>
  493. <label class="alignleft">
  494. <span class="title"><?php _e( 'Visibility', 'woocommerce' ); ?></span>
  495. <span class="input-text-wrap">
  496. <select class="visibility" name="_visibility">
  497. <?php
  498. $options = array(
  499. 'visible' => __( 'Catalog &amp; search', 'woocommerce' ),
  500. 'catalog' => __( 'Catalog', 'woocommerce' ),
  501. 'search' => __( 'Search', 'woocommerce' ),
  502. 'hidden' => __( 'Hidden', 'woocommerce' )
  503. );
  504. foreach ($options as $key => $value) {
  505. echo '<option value="'.$key.'">'. $value .'</option>';
  506. }
  507. ?>
  508. </select>
  509. </span>
  510. </label>
  511. <label class="alignleft featured">
  512. <input type="checkbox" name="_featured" value="1">
  513. <span class="checkbox-title"><?php _e( 'Featured', 'woocommerce' ); ?></span>
  514. </label>
  515. <br class="clear" />
  516. <label class="alignleft">
  517. <span class="title"><?php _e( 'In stock?', 'woocommerce' ); ?></span>
  518. <span class="input-text-wrap">
  519. <select class="stock_status" name="_stock_status">
  520. <?php
  521. $options = array(
  522. 'instock' => __( 'In stock', 'woocommerce' ),
  523. 'outofstock' => __( 'Out of stock', 'woocommerce' )
  524. );
  525. foreach ($options as $key => $value) {
  526. echo '<option value="'.$key.'">'. $value .'</option>';
  527. }
  528. ?>
  529. </select>
  530. </span>
  531. </label>
  532. <div class="stock_fields">
  533. <?php if (get_option('woocommerce_manage_stock')=='yes') : ?>
  534. <label class="alignleft manage_stock">
  535. <input type="checkbox" name="_manage_stock" value="1">
  536. <span class="checkbox-title"><?php _e( 'Manage stock?', 'woocommerce' ); ?></span>
  537. </label>
  538. <br class="clear" />
  539. <label class="stock_qty_field">
  540. <span class="title"><?php _e( 'Stock Qty', 'woocommerce' ); ?></span>
  541. <span class="input-text-wrap">
  542. <input type="text" name="_stock" class="text stock" value="">
  543. </span>
  544. </label>
  545. <?php endif; ?>
  546. </div>
  547. <input type="hidden" name="woocommerce_quick_edit_nonce" value="<?php echo wp_create_nonce( 'woocommerce_quick_edit_nonce' ); ?>" />
  548. </div>
  549. </fieldset>
  550. <?php
  551. }
  552. add_action( 'quick_edit_custom_box', 'woocommerce_admin_product_quick_edit', 10, 2 );
  553. /**
  554. * Custom quick edit - script
  555. *
  556. * @access public
  557. * @param mixed $hook
  558. * @return void
  559. */
  560. function woocommerce_admin_product_quick_edit_scripts( $hook ) {
  561. global $woocommerce, $post_type;
  562. if ( $hook == 'edit.php' && $post_type == 'product' )
  563. wp_enqueue_script( 'woocommerce_quick-edit', $woocommerce->plugin_url() . '/assets/js/admin/quick-edit.js', array('jquery') );
  564. }
  565. add_action( 'admin_enqueue_scripts', 'woocommerce_admin_product_quick_edit_scripts', 10 );
  566. /**
  567. * Custom quick edit - save
  568. *
  569. * @access public
  570. * @param mixed $post_id
  571. * @param mixed $post
  572. * @return void
  573. */
  574. function woocommerce_admin_product_quick_edit_save( $post_id, $post ) {
  575. if ( !$_POST ) return $post_id;
  576. if ( is_int( wp_is_post_revision( $post_id ) ) ) return;
  577. if( is_int( wp_is_post_autosave( $post_id ) ) ) return;
  578. if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;
  579. if ( !isset($_POST['woocommerce_quick_edit_nonce']) || (isset($_POST['woocommerce_quick_edit_nonce']) && !wp_verify_nonce( $_POST['woocommerce_quick_edit_nonce'], 'woocommerce_quick_edit_nonce' ))) return $post_id;
  580. if ( !current_user_can( 'edit_post', $post_id )) return $post_id;
  581. if ( $post->post_type != 'product' ) return $post_id;
  582. global $woocommerce, $wpdb;
  583. $product = get_product( $post );
  584. // Save fields
  585. if(isset($_POST['_sku'])) update_post_meta($post_id, '_sku', esc_html(stripslashes($_POST['_sku'])));
  586. if(isset($_POST['_weight'])) update_post_meta($post_id, '_weight', esc_html(stripslashes($_POST['_weight'])));
  587. if(isset($_POST['_length'])) update_post_meta($post_id, '_length', esc_html(stripslashes($_POST['_length'])));
  588. if(isset($_POST['_width'])) update_post_meta($post_id, '_width', esc_html(stripslashes($_POST['_width'])));
  589. if(isset($_POST['_height'])) update_post_meta($post_id, '_height', esc_html(stripslashes($_POST['_height'])));
  590. if(isset($_POST['_stock_status'])) update_post_meta( $post_id, '_stock_status', stripslashes( $_POST['_stock_status'] ) );
  591. if(isset($_POST['_visibility'])) update_post_meta( $post_id, '_visibility', stripslashes( $_POST['_visibility'] ) );
  592. if(isset($_POST['_featured'])) update_post_meta( $post_id, '_featured', 'yes' ); else update_post_meta( $post_id, '_featured', 'no' );
  593. if ($product->is_type('simple') || $product->is_type('external')) {
  594. if(isset($_POST['_regular_price'])) update_post_meta( $post_id, '_regular_price', stripslashes( $_POST['_regular_price'] ) );
  595. if(isset($_POST['_sale_price'])) update_post_meta( $post_id, '_sale_price', stripslashes( $_POST['_sale_price'] ) );
  596. // Handle price - remove dates and set to lowest
  597. $price_changed = false;
  598. if(isset($_POST['_regular_price']) && stripslashes( $_POST['_regular_price'] )!=$product->regular_price) $price_changed = true;
  599. if(isset($_POST['_sale_price']) && stripslashes( $_POST['_sale_price'] )!=$product->sale_price) $price_changed = true;
  600. if ($price_changed) {
  601. update_post_meta( $post_id, '_sale_price_dates_from', '');
  602. update_post_meta( $post_id, '_sale_price_dates_to', '');
  603. if ($_POST['_sale_price'] != '') {
  604. update_post_meta( $post_id, '_price', stripslashes($_POST['_sale_price']) );
  605. } else {
  606. update_post_meta( $post_id, '_price', stripslashes($_POST['_regular_price']) );
  607. }
  608. }
  609. }
  610. // Handle stock
  611. if (!$product->is_type('grouped')) {
  612. if (isset($_POST['_manage_stock'])) {
  613. update_post_meta( $post_id, '_manage_stock', 'yes' );
  614. update_post_meta( $post_id, '_stock', (int) $_POST['_stock'] );
  615. } else {
  616. update_post_meta( $post_id, '_manage_stock', 'no' );
  617. update_post_meta( $post_id, '_stock', '0' );
  618. }
  619. }
  620. // Clear transient
  621. $woocommerce->clear_product_transients( $post_id );
  622. }
  623. add_action( 'save_post', 'woocommerce_admin_product_quick_edit_save', 10, 2 );
  624. /**
  625. * Custom bulk edit - form
  626. *
  627. * @access public
  628. * @param mixed $column_name
  629. * @param mixed $post_type
  630. * @return void
  631. */
  632. function woocommerce_admin_product_bulk_edit( $column_name, $post_type ) {
  633. if ($column_name != 'price' || $post_type != 'product') return;
  634. ?>
  635. <fieldset class="inline-edit-col-right">
  636. <div id="woocommerce-fields-bulk" class="inline-edit-col">
  637. <h4><?php _e( 'Product Data', 'woocommerce' ); ?></h4>
  638. <div class="inline-edit-group">
  639. <label class="alignleft">
  640. <span class="title"><?php _e( 'Price', 'woocommerce' ); ?></span>
  641. <span class="input-text-wrap">
  642. <select class="change_regular_price change_to" name="change_regular_price">
  643. <?php
  644. $options = array(
  645. '' => __( '— No Change —', 'woocommerce' ),
  646. '1' => __( 'Change to:', 'woocommerce' ),
  647. '2' => __( 'Increase by (fixed amount or %):', 'woocommerce' ),
  648. '3' => __( 'Decrease by (fixed amount or %):', 'woocommerce' )
  649. );
  650. foreach ($options as $key => $value) {
  651. echo '<option value="' . $key . '">' . $value . '</option>';
  652. }
  653. ?>
  654. </select>
  655. </span>
  656. </label>
  657. <label class="alignright">
  658. <input type="text" name="_regular_price" class="text regular_price" placeholder="<?php _e( 'Enter price', 'woocommerce' ); ?>" value="" />
  659. </label>
  660. </div>
  661. <div class="inline-edit-group">
  662. <label class="alignleft">
  663. <span class="title"><?php _e( 'Sale', 'woocommerce' ); ?></span>
  664. <span class="input-text-wrap">
  665. <select class="change_sale_price change_to" name="change_sale_price">
  666. <?php
  667. $options = array(
  668. '' => __( '— No Change —', 'woocommerce' ),
  669. '1' => __( 'Change to:', 'woocommerce' ),
  670. '2' => __( 'Increase by (fixed amount or %):', 'woocommerce' ),
  671. '3' => __( 'Decrease by (fixed amount or %):', 'woocommerce' ),
  672. '4' => __( 'Decrease regular price by (fixed amount or %):', 'woocommerce' )
  673. );
  674. foreach ($options as $key => $value) {
  675. echo '<option value="' . $key . '">' . $value . '</option>';
  676. }
  677. ?>
  678. </select>
  679. </span>
  680. </label>
  681. <label class="alignright">
  682. <input type="text" name="_sale_price" class="text sale_price" placeholder="<?php _e( 'Enter price', 'woocommerce' ); ?>" value="" />
  683. </label>
  684. </div>
  685. <?php if ( get_option('woocommerce_enable_weight') == "yes" ) : ?>
  686. <div class="inline-edit-group">
  687. <label class="alignleft">
  688. <span class="title"><?php _e( 'Weight', 'woocommerce' ); ?></span>
  689. <span class="input-text-wrap">
  690. <select class="change_weight change_to" name="change_weight">
  691. <?php
  692. $options = array(
  693. '' => __( '— No Change —', 'woocommerce' ),
  694. '1' => __( 'Change to:', 'woocommerce' )
  695. );
  696. foreach ($options as $key => $value) {
  697. echo '<option value="'.$key.'">'. $value .'</option>';
  698. }
  699. ?>
  700. </select>
  701. </span>
  702. </label>
  703. <label class="alignright">
  704. <input type="text" name="_weight" class="text weight" placeholder="0.00" value="">
  705. </label>
  706. </div>
  707. <?php endif; ?>
  708. <?php if ( get_option('woocommerce_enable_dimensions') == "yes" ) : ?>
  709. <div class="inline-edit-group dimensions">
  710. <label class="alignleft">
  711. <span class="title"><?php _e( 'L/W/H', 'woocommerce' ); ?></span>
  712. <span class="input-text-wrap">
  713. <select class="change_dimensions change_to" name="change_dimensions">
  714. <?php
  715. $options = array(
  716. '' => __( '— No Change —', 'woocommerce' ),
  717. '1' => __( 'Change to:', 'woocommerce' )
  718. );
  719. foreach ($options as $key => $value) {
  720. echo '<option value="'.$key.'">'. $value .'</option>';
  721. }
  722. ?>
  723. </select>
  724. </span>
  725. </label>
  726. <div class="alignright">
  727. <input type="text" name="_length" class="text length" placeholder="<?php _e( 'Length', 'woocommerce' ); ?>" value="">
  728. <input type="text" name="_width" class="text width" placeholder="<?php _e( 'Width', 'woocommerce' ); ?>" value="">
  729. <input type="text" name="_height" class="text height" placeholder="<?php _e( 'Height', 'woocommerce' ); ?>" value="">
  730. </div>
  731. </div>
  732. <?php endif; ?>
  733. <label>
  734. <span class="title"><?php _e( 'Visibility', 'woocommerce' ); ?></span>
  735. <span class="input-text-wrap">
  736. <select class="visibility" name="_visibility">
  737. <?php
  738. $options = array(
  739. '' => __( '— No Change —', 'woocommerce' ),
  740. 'visible' => __( 'Catalog &amp; search', 'woocommerce' ),
  741. 'catalog' => __( 'Catalog', 'woocommerce' ),
  742. 'search' => __( 'Search', 'woocommerce' ),
  743. 'hidden' => __( 'Hidden', 'woocommerce' )
  744. );
  745. foreach ($options as $key => $value) {
  746. echo '<option value="'.$key.'">'. $value .'</option>';
  747. }
  748. ?>
  749. </select>
  750. </span>
  751. </label>
  752. <label>
  753. <span class="title"><?php _e( 'Featured', 'woocommerce' ); ?></span>
  754. <span class="input-text-wrap">
  755. <select class="featured" name="_featured">
  756. <?php
  757. $options = array(
  758. '' => __( '— No Change —', 'woocommerce' ),
  759. 'yes' => __( 'Yes', 'woocommerce' ),
  760. 'no' => __( 'No', 'woocommerce' )
  761. );
  762. foreach ($options as $key => $value) {
  763. echo '<option value="'.$key.'">'. $value .'</option>';
  764. }
  765. ?>
  766. </select>
  767. </span>
  768. </label>
  769. <label>
  770. <span class="title"><?php _e( 'In stock?', 'woocommerce' ); ?></span>
  771. <span class="input-text-wrap">
  772. <select class="stock_status" name="_stock_status">
  773. <?php
  774. $options = array(
  775. '' => __( '— No Change —', 'woocommerce' ),
  776. 'instock' => __( 'In stock', 'woocommerce' ),
  777. 'outofstock' => __( 'Out of stock', 'woocommerce' )
  778. );
  779. foreach ($options as $key => $value) {
  780. echo '<option value="'.$key.'">'. $value .'</option>';
  781. }
  782. ?>
  783. </select>
  784. </span>
  785. </label>
  786. <?php if (get_option('woocommerce_manage_stock')=='yes') : ?>
  787. <label>
  788. <span class="title"><?php _e( 'Manage stock?', 'woocommerce' ); ?></span>
  789. <span class="input-text-wrap">
  790. <select class="manage_stock" name="_manage_stock">
  791. <?php
  792. $options = array(
  793. '' => __( '— No Change —', 'woocommerce' ),
  794. 'yes' => __( 'Yes', 'woocommerce' ),
  795. 'no' => __( 'No', 'woocommerce' )
  796. );
  797. foreach ($options as $key => $value) {
  798. echo '<option value="'.$key.'">'. $value .'</option>';
  799. }
  800. ?>
  801. </select>
  802. </span>
  803. </label>
  804. <div class="inline-edit-group dimensions">
  805. <label class="alignleft stock_qty_field">
  806. <span class="title"><?php _e( 'Stock Qty', 'woocommerce' ); ?></span>
  807. <span class="input-text-wrap">
  808. <select class="change_stock change_to" name="change_stock">
  809. <?php
  810. $options = array(
  811. '' => __( '— No Change —', 'woocommerce' ),
  812. '1' => __( 'Change to:', 'woocommerce' )
  813. );
  814. foreach ($options as $key => $value) {
  815. echo '<option value="'.$key.'">'. $value .'</option>';
  816. }
  817. ?>
  818. </select>
  819. </span>
  820. </label>
  821. <label class="alignright">
  822. <input type="text" name="_stock" class="text stock" placeholder="<?php _e( 'Stock Qty', 'woocommerce' ); ?>" value="">
  823. </label>
  824. </div>
  825. <?php endif; ?>
  826. <input type="hidden" name="woocommerce_bulk_edit_nonce" value="<?php echo wp_create_nonce( 'woocommerce_bulk_edit_nonce' ); ?>" />
  827. </div>
  828. </fieldset>
  829. <?php
  830. }
  831. add_action('bulk_edit_custom_box', 'woocommerce_admin_product_bulk_edit', 10, 2);
  832. /**
  833. * Custom bulk edit - save
  834. *
  835. * @access public
  836. * @param mixed $post_id
  837. * @param mixed $post
  838. * @return void
  839. */
  840. function woocommerce_admin_product_bulk_edit_save( $post_id, $post ) {
  841. if ( is_int( wp_is_post_revision( $post_id ) ) ) return;
  842. if ( is_int( wp_is_post_autosave( $post_id ) ) ) return;
  843. if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;
  844. if ( ! isset( $_REQUEST['woocommerce_bulk_edit_nonce'] ) || ! wp_verify_nonce( $_REQUEST['woocommerce_bulk_edit_nonce'], 'woocommerce_bulk_edit_nonce' ) ) return $post_id;
  845. if ( ! current_user_can( 'edit_post', $post_id ) ) return $post_id;
  846. if ( $post->post_type != 'product' ) return $post_id;
  847. global $woocommerce, $wpdb;
  848. $product = get_product( $post );
  849. // Save fields
  850. if ( ! empty( $_REQUEST['change_weight'] ) && isset( $_REQUEST['_weight'] ) )
  851. update_post_meta( $post_id, '_weight', esc_html( stripslashes( $_REQUEST['_weight'] ) ) );
  852. if ( ! empty( $_REQUEST['change_dimensions'] ) ) {
  853. if ( isset( $_REQUEST['_length'] ) )
  854. update_post_meta( $post_id, '_length', esc_html( stripslashes( $_REQUEST['_length'] ) ) );
  855. if ( isset( $_REQUEST['_width'] ) )
  856. update_post_meta( $post_id, '_width', esc_html( stripslashes( $_REQUEST['_width'] ) ) );
  857. if ( isset( $_REQUEST['_height'] ) )
  858. update_post_meta( $post_id, '_height', esc_html( stripslashes( $_REQUEST['_height'] ) ) );
  859. }
  860. if ( ! empty( $_REQUEST['_stock_status'] ) )
  861. update_post_meta( $post_id, '_stock_status', stripslashes( $_REQUEST['_stock_status'] ) );
  862. if ( ! empty( $_REQUEST['_visibility'] ) )
  863. update_post_meta( $post_id, '_visibility', stripslashes( $_REQUEST['_visibility'] ) );
  864. if ( ! empty( $_REQUEST['_featured'] ) )
  865. update_post_meta( $post_id, '_featured', stripslashes( $_REQUEST['_featured'] ) );
  866. // Handle price - remove dates and set to lowest
  867. if ( $product->is_type( 'simple' ) || $product->is_type( 'external' ) ) {
  868. $price_changed = false;
  869. if ( ! empty( $_REQUEST['change_regular_price'] ) ) {
  870. $old_price = $product->regular_price;
  871. $change_regular_price = absint( $_REQUEST['change_regular_price'] );
  872. $regular_price = esc_attr( stripslashes( $_REQUEST['_regular_price'] ) );
  873. switch ( $change_regular_price ) {
  874. case 1 :
  875. $new_price = $regular_price;
  876. break;
  877. case 2 :
  878. if ( strstr( $regular_price, '%' ) ) {
  879. $percent = str_replace( '%', '', $regular_price ) / 100;
  880. $new_price = $old_price + ( $old_price * $percent );
  881. } else {
  882. $new_price = $old_price + $regular_price;
  883. }
  884. break;
  885. case 3 :
  886. if ( strstr( $regular_price, '%' ) ) {
  887. $percent = str_replace( '%', '', $regular_price ) / 100;
  888. $new_price = $old_price - ( $old_price * $percent );
  889. } else {
  890. $new_price = $old_price - $regular_price;
  891. }
  892. break;
  893. }
  894. if ( isset( $new_price ) && $new_price != $product->regular_price ) {
  895. $price_changed = true;
  896. update_post_meta( $post_id, '_regular_price', $new_price );
  897. $product->regular_price = $new_price;
  898. }
  899. }
  900. if ( ! empty( $_REQUEST['change_sale_price'] ) ) {
  901. $old_price = $product->sale_price;
  902. $change_sale_price = absint( $_REQUEST['change_sale_price'] );
  903. $sale_price = esc_attr( stripslashes( $_REQUEST['_sale_price'] ) );
  904. switch ( $change_sale_price ) {
  905. case 1 :
  906. $new_price = $sale_price;
  907. break;
  908. case 2 :
  909. if ( strstr( $sale_price, '%' ) ) {
  910. $percent = str_replace( '%', '', $sale_price ) / 100;
  911. $new_price = $old_price + ( $old_price * $percent );
  912. } else {
  913. $new_price = $old_price + $sale_price;
  914. }
  915. break;
  916. case 3 :
  917. if ( strstr( $sale_price, '%' ) ) {
  918. $percent = str_replace( '%', '', $sale_price ) / 100;
  919. $new_price = $old_price - ( $old_price * $percent );
  920. } else {
  921. $new_price = $old_price - $sale_price;
  922. }
  923. break;
  924. case 4 :
  925. if ( strstr( $sale_price, '%' ) ) {
  926. $percent = str_replace( '%', '', $sale_price ) / 100;
  927. $new_price = $product->regular_price - ( $product->regular_price * $percent );
  928. } else {
  929. $new_price = $product->regular_price - $sale_price;
  930. }
  931. break;
  932. }
  933. if ( isset( $new_price ) && $new_price != $product->sale_price ) {
  934. $price_changed = true;
  935. update_post_meta( $post_id, '_sale_price', $new_price );
  936. $product->sale_price = $new_price;
  937. }
  938. }
  939. if ( $price_changed ) {
  940. update_post_meta( $post_id, '_sale_price_dates_from', '' );
  941. update_post_meta( $post_id, '_sale_price_dates_to', '' );
  942. if ( $product->regular_price < $product->sale_price ) {
  943. $product->sale_price = '';
  944. update_post_meta( $post_id, '_sale_price', '' );
  945. }
  946. if ( $product->sale_price ) {
  947. update_post_meta( $post_id, '_price', $product->sale_price );
  948. } else {
  949. update_post_meta( $post_id, '_price', $product->regular_price );
  950. }
  951. }
  952. }
  953. // Handle stock
  954. if ( ! $product->is_type( 'grouped' ) ) {
  955. if ( ! empty( $_REQUEST['change_stock'] ) ) {
  956. update_post_meta( $post_id, '_stock', (int) $_REQUEST['_stock'] );
  957. update_post_meta( $post_id, '_manage_stock', 'yes' );
  958. }
  959. if ( ! empty( $_REQUEST['_manage_stock'] ) ) {
  960. if ( $_REQUEST['_manage_stock'] == 'yes' ) {
  961. update_post_meta( $post_id, '_manage_stock', 'yes' );
  962. } else {
  963. update_post_meta( $post_id, '_manage_stock', 'no' );
  964. update_post_meta( $post_id, '_stock', '0' );
  965. }
  966. }
  967. }
  968. // Clear transient
  969. $woocommerce->clear_product_transients( $post_id );
  970. }
  971. add_action( 'save_post', 'woocommerce_admin_product_bulk_edit_save', 10, 2 );
  972. /**
  973. * Product sorting link
  974. *
  975. * Based on Simple Page Ordering by 10up (http://wordpress.org/extend/plugins/simple-page-ordering/)
  976. *
  977. * @access public
  978. * @param mixed $views
  979. * @return void
  980. */
  981. function woocommerce_default_sorting_link( $views ) {
  982. global $post_type, $wp_query;
  983. if ( ! current_user_can('edit_others_pages') ) return $views;
  984. $class = ( isset( $wp_query->query['orderby'] ) && $wp_query->query['orderby'] == 'menu_order title' ) ? 'current' : '';
  985. $query_string = remove_query_arg(array( 'orderby', 'order' ));
  986. $query_string = add_query_arg( 'orderby', urlencode('menu_order title'), $query_string );
  987. $query_string = add_query_arg( 'order', urlencode('ASC'), $query_string );
  988. $views['byorder'] = '<a href="'. $query_string . '" class="' . $class . '">' . __( 'Sort Products', 'woocommerce' ) . '</a>';
  989. return $views;
  990. }
  991. add_filter( 'views_edit-product', 'woocommerce_default_sorting_link' );
  992. /**
  993. * woocommerce_disable_checked_ontop function.
  994. *
  995. * @access public
  996. * @param mixed $args
  997. * @param mixed $post_id
  998. * @return void
  999. */
  1000. function woocommerce_disable_checked_ontop( $args ) {
  1001. if ( $args['taxonomy'] == 'product_cat' ) {
  1002. $args['checked_ontop'] = false;
  1003. }
  1004. return $args;
  1005. }
  1006. add_filter( 'wp_terms_checklist_args', 'woocommerce_disable_checked_ontop' );