Drag and drop term ordering (so variation options can be sorted) Closes #57.

This commit is contained in:
Mike Jolley 2011-10-12 18:32:30 +01:00
parent 9a1aec5c90
commit f8447c7a46
10 changed files with 115 additions and 79 deletions

View File

@ -54,7 +54,7 @@ function woocommerce_admin_scripts() {
$suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
// Register scripts // Register scripts
wp_register_script( 'woocommerce_admin', $woocommerce->plugin_url() . '/assets/js/admin/woocommerce_admin'.$suffix.'.js', array('jquery', 'jquery-ui-widget'), '1.0' ); wp_register_script( 'woocommerce_admin', $woocommerce->plugin_url() . '/assets/js/admin/woocommerce_admin'.$suffix.'.js', array('jquery', 'jquery-ui-widget', 'jquery-ui-core'), '1.0' );
wp_register_script( 'jquery-ui-datepicker', $woocommerce->plugin_url() . '/assets/js/admin/ui-datepicker.js', array('jquery','jquery-ui-core'), '1.0' ); wp_register_script( 'jquery-ui-datepicker', $woocommerce->plugin_url() . '/assets/js/admin/ui-datepicker.js', array('jquery','jquery-ui-core'), '1.0' );
wp_register_script( 'woocommerce_writepanel', $woocommerce->plugin_url() . '/assets/js/admin/write-panels'.$suffix.'.js', array('jquery', 'jquery-ui-datepicker') ); wp_register_script( 'woocommerce_writepanel', $woocommerce->plugin_url() . '/assets/js/admin/write-panels'.$suffix.'.js', array('jquery', 'jquery-ui-datepicker') );
@ -108,6 +108,22 @@ function woocommerce_admin_scripts() {
endif; endif;
// Term ordering
if ($screen->id=='edit-product_cat' || strstr($screen->id, 'edit-pa_')) :
wp_register_script( 'woocommerce_term_ordering', $woocommerce->plugin_url() . '/assets/js/admin/term-ordering.js', array('jquery-ui-sortable') );
wp_enqueue_script( 'woocommerce_term_ordering' );
$taxonomy = (isset($_GET['taxonomy'])) ? $_GET['taxonomy'] : '';
$woocommerce_term_order_params = array(
'taxonomy' => $taxonomy
);
wp_localize_script( 'woocommerce_term_ordering', 'woocommerce_term_ordering_params', $woocommerce_term_order_params );
endif;
// Reports pages // Reports pages
if ($screen->id=='woocommerce_page_woocommerce_reports') : if ($screen->id=='woocommerce_page_woocommerce_reports') :
@ -119,6 +135,7 @@ function woocommerce_admin_scripts() {
} }
add_action('admin_enqueue_scripts', 'woocommerce_admin_scripts'); add_action('admin_enqueue_scripts', 'woocommerce_admin_scripts');
/** /**
* Queue admin CSS * Queue admin CSS
*/ */
@ -201,45 +218,32 @@ function woocommerce_admin_head() {
} }
add_action('admin_head', 'woocommerce_admin_head'); add_action('admin_head', 'woocommerce_admin_head');
/**
* Categories ordering scripts
*/
function woocommerce_categories_scripts() {
global $woocommerce;
if( !isset($_GET['taxonomy']) || $_GET['taxonomy'] !== 'product_cat') return;
wp_register_script('woocommerce-categories-ordering', $woocommerce->plugin_url() . '/assets/js/admin/categories-ordering.js', array('jquery-ui-sortable'));
wp_print_scripts('woocommerce-categories-ordering');
}
add_action('admin_footer-edit-tags.php', 'woocommerce_categories_scripts');
/** /**
* Ajax request handling for categories ordering * Ajax request handling for categories ordering
*/ */
function woocommerce_categories_ordering() { function woocommerce_term_ordering() {
global $wpdb; global $wpdb;
$id = (int)$_POST['id']; $id = (int) $_POST['id'];
$next_id = isset($_POST['nextid']) && (int) $_POST['nextid'] ? (int) $_POST['nextid'] : null; $next_id = isset($_POST['nextid']) && (int) $_POST['nextid'] ? (int) $_POST['nextid'] : null;
$taxonomy = isset($_POST['thetaxonomy']) ? esc_attr( $_POST['thetaxonomy'] ) : null;
$term = get_term_by('id', $id, $taxonomy);
if( ! $id || ! $term = get_term_by('id', $id, 'product_cat') ) die(0); if( !$id || !$term || !$taxonomy ) die(0);
woocommerce_order_categories( $term, $next_id ); woocommerce_order_terms( $term, $next_id, $taxonomy );
$children = get_terms($taxonomy, "child_of=$id&menu_order=ASC&hide_empty=0");
$children = get_terms('product_cat', "child_of=$id&menu_order=ASC&hide_empty=0");
if( $term && sizeof($children) ) { if( $term && sizeof($children) ) {
echo 'children'; echo 'children';
die; die;
} }
} }
add_action('wp_ajax_woocommerce-categories-ordering', 'woocommerce_categories_ordering'); add_action('wp_ajax_woocommerce-term-ordering', 'woocommerce_term_ordering');
/** /**
* Search by SKU ro ID for products. Adapted from code by BenIrvin (Admin Search by ID) * Search by SKU or ID for products. Adapted from code by BenIrvin (Admin Search by ID)
*/ */
if (is_admin()) : if (is_admin()) :
add_action('parse_request', 'woocommerce_admin_product_search'); add_action('parse_request', 'woocommerce_admin_product_search');

View File

@ -134,45 +134,39 @@ function woocommerce_category_thumbnail_field_save( $term_id, $tt_id, $taxonomy
/** /**
* Categories ordering * Category/Term ordering
*/ */
/** /**
* Reorder on category insertion * Reorder on term insertion
*
* @param int $term_id
*/ */
add_action("create_product_cat", 'woocommerce_create_product_cat'); add_action("create_term", 'woocommerce_create_term');
function woocommerce_create_product_cat ($term_id) { function woocommerce_create_term( $term_id, $tt_id, $taxonomy ) {
$next_id = null; $next_id = null;
$term = get_term($term_id, 'product_cat'); $term = get_term($term_id, $taxonomy);
// gets the sibling terms // gets the sibling terms
$siblings = get_terms('product_cat', "parent={$term->parent}&menu_order=ASC&hide_empty=0"); $siblings = get_terms($taxonomy, "parent={$term->parent}&menu_order=ASC&hide_empty=0");
foreach ($siblings as $sibling) { foreach ($siblings as $sibling) {
if( $sibling->term_id == $term_id ) continue; if( $sibling->term_id == $term_id ) continue;
$next_id = $sibling->term_id; // first sibling term of the hierachy level $next_id = $sibling->term_id; // first sibling term of the hierarchy level
break; break;
} }
// reorder // reorder
woocommerce_order_categories ( $term, $next_id ); woocommerce_order_terms( $term, $next_id, $taxonomy );
} }
/** /**
* Delete terms metas on deletion * Delete terms metas on deletion
*
* @param int $term_id
*/ */
add_action("delete_product_cat", 'woocommerce_delete_product_cat'); add_action("delete_product_term", 'woocommerce_delete_term');
function woocommerce_delete_product_cat($term_id) { function woocommerce_delete_term( $term_id, $tt_id, $taxonomy ) {
$term_id = (int) $term_id; $term_id = (int) $term_id;
@ -183,18 +177,17 @@ function woocommerce_delete_product_cat($term_id) {
} }
/** /**
* Move a category before the a given element of its hierarchy level * Move a term before the a given element of its hierarchy level
* *
* @param object $the_term * @param object $the_term
* @param int $next_id the id of the next slibling element in save hierachy level * @param int $next_id the id of the next slibling element in save hierachy level
* @param int $index * @param int $index
* @param int $terms * @param int $terms
*/ */
function woocommerce_order_categories ( $the_term, $next_id, $index=0, $terms=null ) { function woocommerce_order_terms( $the_term, $next_id, $taxonomy, $index=0, $terms=null ) {
if( ! $terms ) $terms = get_terms('product_cat', 'menu_order=ASC&hide_empty=0&parent=0'); if( ! $terms ) $terms = get_terms($taxonomy, 'menu_order=ASC&hide_empty=0&parent=0');
if( empty( $terms ) ) return $index; if( empty( $terms ) ) return $index;
$id = $the_term->term_id; $id = $the_term->term_id;
@ -210,50 +203,50 @@ function woocommerce_order_categories ( $the_term, $next_id, $index=0, $terms=nu
// the nextid of our term to order, lets move our term here // the nextid of our term to order, lets move our term here
if(null !== $next_id && $term->term_id == $next_id) { if(null !== $next_id && $term->term_id == $next_id) {
$index++; $index++;
$index = woocommerce_set_category_order($id, $index, true); $index = woocommerce_set_term_order($id, $index, $taxonomy, true);
} }
// set order // set order
$index++; $index++;
$index = woocommerce_set_category_order($term->term_id, $index); $index = woocommerce_set_term_order($term->term_id, $index, $taxonomy);
// if that term has children we walk through them // if that term has children we walk through them
$children = get_terms('product_cat', "parent={$term->term_id}&menu_order=ASC&hide_empty=0"); $children = get_terms($taxonomy, "parent={$term->term_id}&menu_order=ASC&hide_empty=0");
if( !empty($children) ) { if( !empty($children) ) {
$index = woocommerce_order_categories ( $the_term, $next_id, $index, $children ); $index = woocommerce_order_terms( $the_term, $next_id, $taxonomy, $index, $children );
} }
} }
// no nextid meaning our term is in last position // no nextid meaning our term is in last position
if( $term_in_level && null === $next_id ) if( $term_in_level && null === $next_id )
$index = woocommerce_set_category_order($id, $index+1, true); $index = woocommerce_set_term_order($id, $index+1, $taxonomy, true);
return $index; return $index;
} }
/** /**
* Set the sort order of a category * Set the sort order of a term
* *
* @param int $term_id * @param int $term_id
* @param int $index * @param int $index
* @param bool $recursive * @param bool $recursive
*/ */
function woocommerce_set_category_order ($term_id, $index, $recursive=false) { function woocommerce_set_term_order($term_id, $index, $taxonomy, $recursive=false) {
global $wpdb; global $wpdb;
$term_id = (int) $term_id; $term_id = (int) $term_id;
$index = (int) $index; $index = (int) $index;
update_metadata('woocommerce_term', $term_id, 'order', $index); update_woocommerce_term_meta( $term_id, 'order', $index );
if( ! $recursive ) return $index; if( ! $recursive ) return $index;
$children = get_terms('product_cat', "parent=$term_id&menu_order=ASC&hide_empty=0"); $children = get_terms($taxonomy, "parent=$term_id&menu_order=ASC&hide_empty=0");
foreach ( $children as $term ) { foreach ( $children as $term ) {
$index ++; $index ++;
$index = woocommerce_set_category_order ($term->term_id, $index, true); $index = woocommerce_set_term_order($term->term_id, $index, $taxonomy, true);
} }
return $index; return $index;

View File

@ -7,7 +7,7 @@ jQuery(document).ready(function($) {
items: 'tr:not(.inline-edit-row)', items: 'tr:not(.inline-edit-row)',
cursor: 'move', cursor: 'move',
axis: 'y', axis: 'y',
containment: 'table.widefat', //containment: 'table.widefat',
placeholder: 'product-cat-placeholder', placeholder: 'product-cat-placeholder',
scrollSensitivity: 40, scrollSensitivity: 40,
helper: function(e, ui) { helper: function(e, ui) {
@ -53,7 +53,7 @@ jQuery(document).ready(function($) {
ui.item.find('.check-column input').hide().after('<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />'); ui.item.find('.check-column input').hide().after('<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />');
// go do the sorting stuff via ajax // go do the sorting stuff via ajax
$.post( ajaxurl, { action: 'woocommerce-categories-ordering', id: termid, nextid: nexttermid }, function(response){ $.post( ajaxurl, { action: 'woocommerce-term-ordering', id: termid, nextid: nexttermid, thetaxonomy: woocommerce_term_ordering_params.taxonomy }, function(response){
if ( response == 'children' ) window.location.reload(); if ( response == 'children' ) window.location.reload();
else { else {
ui.item.find('.check-column input').show().siblings('img').remove(); ui.item.find('.check-column input').show().siblings('img').remove();

View File

@ -272,6 +272,23 @@ class woocommerce_order {
} }
/** Returns true if the order contains a downloadable product */
function has_downloadable_item() {
$has_downloadable_item = false;
foreach($this->items as $item) :
$_product = $this->get_product_from_item( $item );
if ($_product->exists && $_product->is_type('downloadable')) :
$has_downloadable_item = true;
endif;
endforeach;
return $has_downloadable_item;
}
/** Generates a URL so that a customer can checkout/pay for their (unpaid - pending) order via a link */ /** Generates a URL so that a customer can checkout/pay for their (unpaid - pending) order via a link */
function get_checkout_payment_url() { function get_checkout_payment_url() {

View File

@ -2,8 +2,8 @@
Contributors: woothemes Contributors: woothemes
Tags: ecommerce, e-commerce, commerce, woothemes, wordpress ecommerce, store, shop, shopping, cart, checkout, widgets, reports, shipping, tax, paypal, inventory Tags: ecommerce, e-commerce, commerce, woothemes, wordpress ecommerce, store, shop, shopping, cart, checkout, widgets, reports, shipping, tax, paypal, inventory
Requires at least: 3.1 Requires at least: 3.1
Tested up to: 3.2 Tested up to: 3.3
Stable tag: 1.0.3 Stable tag: 1.1
An e-commerce toolkit that helps you sell anything. Beautifully. An e-commerce toolkit that helps you sell anything. Beautifully.
@ -57,7 +57,8 @@ For further documentation on using WooCommerce, please sign up for free at http:
== Changelog == == Changelog ==
= 1.1 - xx/10/2011 = = 1.1 - 12/10/2011 =
* Tested and working with WordPress 3.3 beta-1
* Added a hook for payment complete order status * Added a hook for payment complete order status
* Added woocommerce term meta api * Added woocommerce term meta api
* Added ability to upload category thumbnails * Added ability to upload category thumbnails
@ -74,9 +75,11 @@ For further documentation on using WooCommerce, please sign up for free at http:
* Password field type for gateways API * Password field type for gateways API
* Front page shop improvements/correct title tags * Front page shop improvements/correct title tags
* Added option for controlling product permalinks * Added option for controlling product permalinks
* Shop page title option
* Load admin css only where needed * Load admin css only where needed
* Admin JS cleanup * Admin JS cleanup
* Removed error message when clicking buttons to view variations/grouped * Removed error message when clicking buttons to view variations/grouped
* Drag and drop term ordering (so variation options can be sorted)
= 1.0.3 - 06/10/2011 = = 1.0.3 - 06/10/2011 =
* Several minor fixes/tweaks * Several minor fixes/tweaks

View File

@ -3,11 +3,11 @@
Plugin Name: WooCommerce Plugin Name: WooCommerce
Plugin URI: http://www.woothemes.com/woocommerce/ Plugin URI: http://www.woothemes.com/woocommerce/
Description: An eCommerce plugin for wordpress. Description: An eCommerce plugin for wordpress.
Version: 1.0.3 Version: 1.1
Author: WooThemes Author: WooThemes
Author URI: http://woothemes.com Author URI: http://woothemes.com
Requires at least: 3.1 Requires at least: 3.1
Tested up to: 3.2 Tested up to: 3.3
*/ */
if (!session_id()) session_start(); if (!session_id()) session_start();
@ -21,7 +21,7 @@ load_plugin_textdomain('woothemes', false, dirname( plugin_basename( __FILE__ )
* Constants * Constants
**/ **/
if (!defined('WOOCOMMERCE_TEMPLATE_URL')) define('WOOCOMMERCE_TEMPLATE_URL', 'woocommerce/'); if (!defined('WOOCOMMERCE_TEMPLATE_URL')) define('WOOCOMMERCE_TEMPLATE_URL', 'woocommerce/');
if (!defined("WOOCOMMERCE_VERSION")) define("WOOCOMMERCE_VERSION", "1.0.3"); if (!defined("WOOCOMMERCE_VERSION")) define("WOOCOMMERCE_VERSION", "1.1");
if (!defined("PHP_EOL")) define("PHP_EOL", "\r\n"); if (!defined("PHP_EOL")) define("PHP_EOL", "\r\n");
/** /**

View File

@ -159,9 +159,15 @@ function woocommerce_completed_order_customer_notification( $id ) {
$order = &new woocommerce_order( $order_id ); $order = &new woocommerce_order( $order_id );
$email_heading = __('Order Complete', 'woothemes'); if ($order->has_downloadable_item()) :
$email_heading = __('Order Complete/Download Links', 'woothemes');
else :
$email_heading = __('Order Complete', 'woothemes');
endif;
$subject = '[' . get_bloginfo('name') . '] ' . __('Order Complete', 'woothemes'); $email_heading = apply_filters('woocommerce_completed_order_customer_notification_subject', $email_heading);
$subject = '[' . get_bloginfo('name') . '] ' . $email_heading;
// Buffer // Buffer
ob_start(); ob_start();

View File

@ -320,7 +320,7 @@ add_filter( 'post_type_link', 'woocommerce_product_cat_filter_post_link', 10, 4
/** /**
* Add product_cat ordering to get_terms * Add term ordering to get_terms
* *
* It enables the support a 'menu_order' parameter to get_terms for the product_cat taxonomy. * It enables the support a 'menu_order' parameter to get_terms for the product_cat taxonomy.
* By default it is 'ASC'. It accepts 'DESC' too * By default it is 'ASC'. It accepts 'DESC' too
@ -331,10 +331,17 @@ add_filter( 'post_type_link', 'woocommerce_product_cat_filter_post_link', 10, 4
add_filter( 'terms_clauses', 'woocommerce_terms_clauses', 10, 3); add_filter( 'terms_clauses', 'woocommerce_terms_clauses', 10, 3);
function woocommerce_terms_clauses($clauses, $taxonomies, $args ) { function woocommerce_terms_clauses($clauses, $taxonomies, $args ) {
global $wpdb; global $wpdb, $woocommerce;
// wordpress should give us the taxonomies asked when calling the get_terms function // wordpress should give us the taxonomies asked when calling the get_terms function. Only apply to categories and pa_ attributes
if( !in_array('product_cat', (array)$taxonomies) ) return $clauses; $found = false;
foreach ((array) $taxonomies as $taxonomy) :
if ($taxonomy=='product_cat' || strstr($taxonomy, 'pa_')) :
$found = true;
break;
endif;
endforeach;
if (!$found) return $clauses;
// query order // query order
if( isset($args['menu_order']) && !$args['menu_order']) return $clauses; // menu_order is false so we do not add order clause if( isset($args['menu_order']) && !$args['menu_order']) return $clauses; // menu_order is false so we do not add order clause

View File

@ -395,22 +395,28 @@ if (!function_exists('woocommerce_variable_add_to_cart')) {
<form action="<?php echo esc_url( $_product->add_to_cart_url() ); ?>" class="variations_form cart" method="post"> <form action="<?php echo esc_url( $_product->add_to_cart_url() ); ?>" class="variations_form cart" method="post">
<table class="variations" cellspacing="0"> <table class="variations" cellspacing="0">
<tbody> <tbody>
<?php foreach ($attributes as $name => $options) :?> <?php foreach ($attributes as $name => $options) : ?>
<tr> <tr>
<td><label for="<?php echo sanitize_title($name); ?>"><?php echo $woocommerce->attribute_label($name); ?></label></td> <td><label for="<?php echo sanitize_title($name); ?>"><?php echo $woocommerce->attribute_label($name); ?></label></td>
<td><select id="<?php echo esc_attr( sanitize_title($name) ); ?>" name="attribute_<?php echo sanitize_title($name); ?>"> <td><select id="<?php echo esc_attr( sanitize_title($name) ); ?>" name="attribute_<?php echo sanitize_title($name); ?>">
<option value=""><?php echo __('Choose an option', 'woothemes') ?>&hellip;</option> <option value=""><?php echo __('Choose an option', 'woothemes') ?>&hellip;</option>
<?php if(is_array($options)) : ?> <?php if(is_array($options)) : ?>
<?php foreach ($options as $option) : <?php
$option_term = get_term_by('slug', $option, $name); // Get terms if this is a taxonomy - ordered
if (!is_wp_error($option_term) && isset($option_term->name)) : if (taxonomy_exists(sanitize_title($name))) :
$term_name = $option_term->name; $args = array('menu_order' => 'ASC');
$terms = get_terms( sanitize_title($name), $args );
foreach ($terms as $term) :
if (!in_array($term->slug, $options)) continue;
echo '<option value="'.$term->slug.'">'.$term->name.'</option>';
endforeach;
else : else :
$term_name = $option; foreach ($options as $option) :
echo '<option value="'.$option.'">'.$option.'</option>';
endforeach;
endif; endif;
?> ?>
<?php echo '<option value="'.$option.'">'.$term_name.'</option>'; ?>
<?php endforeach; ?>
<?php endif;?> <?php endif;?>
</td> </td>
</tr> </tr>