diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..365480cc328 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,29 @@ + + +## EXPLANATION OF THE ISSUE + +What happens, under which versions, under what conditions, when, and what were you expecting instead. + +## STEPS TO REPRODUCE THE ISSUE + +1. List steps to reproduce your issue so we can replicate. + +## SYSTEM STATUS REPORT + +``` +Grab the system status report from WooCommerce > System Status and paste it here. +``` diff --git a/.scrutinizer.yml b/.scrutinizer.yml index a98f292be23..7f292d863dd 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -4,8 +4,7 @@ filter: - apigen/* - dummy-data/* - i18n/* - - includes/api/v1/* - - includes/api/v2/* + - includes/api/legacy/* - includes/libraries/* - includes/updates/* - includes/gateways/simplify-commerce/includes/* diff --git a/.travis.yml b/.travis.yml index dce0e441f28..dc68322dd1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,23 +2,30 @@ language: php sudo: false +# Test main supported versions of PHP and HHVM against latest WP. 5.2 is min supported version. php: + - 5.2 - 5.3 - 5.4 - 5.5 - 5.6 + - 7.0 + - hhvm env: - WP_VERSION=latest WP_MULTISITE=0 - - WP_VERSION=4.3 WP_MULTISITE=0 - - WP_VERSION=4.2 WP_MULTISITE=0 - - WP_VERSION=4.1 WP_MULTISITE=0 - - WP_VERSION=4.0 WP_MULTISITE=0 +# Additonal tests against stable PHP (min recommended version is 5.6) and past supported versions of WP. matrix: include: - - php: 5.3 + - php: 5.6 env: WP_VERSION=latest WP_MULTISITE=1 + - php: 5.6 + env: WP_VERSION=4.3 WP_MULTISITE=0 + - php: 5.6 + env: WP_VERSION=4.2 WP_MULTISITE=0 + - php: 5.6 + env: WP_VERSION=4.1 WP_MULTISITE=0 before_script: - bash tests/bin/install.sh woocommerce_test root '' localhost $WP_VERSION diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 76e5b403625..7c2250736d1 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,180 @@ == Changelog == += 2.5.5 - 11/03/2016 = +* Fix - Before running dbdelta, drop indexes to prevent duplicate key notices. +* Fix - Prevent notice when unsetting terms on product edit screen. +* Tweak - zeroclipboard fallback for firefox on system status report. +* Tweak - Check valid product ID is provided on add_to_cart shortcode. + += 2.5.4 - 10/03/2016 = +* Fix - Fix table creation when using utf8mb4 charset. +* Fix - Have wp_insert_post return WP_Error when creating our coupon, so the is_wp_error check can catch it. +* Fix - Clear sale price on save if sale is no longer valid. +* Fix - Round refund values to ensure refunds can be performed. +* Fix - When getting coupon by code used twice, latest should be queried. +* Fix - CLI improvements for setting up variations and deleting orders. +* Fix - Allow big selects when getting variations to support larger queries. +* Fix - Trigger webhook when user edits addresses on frontend. +* Fix - Hide shipping row when calculator is disabled, and shipping costs are hidden. +* Fix - Unset deleted attributes when updating products. +* Tweak - Update date for paid orders during non-manual updates only. +* Tweak - wc_get_page_permalink - if the page ID is not set, redirect home instead to prevent white screens. +* Tweak - Remove log dir from system status report. +* Tweak - When sorting by date, fallback to ID. +* Tweak - Rename pay link for clarity. +* Tweak - Provide a fallback message if copying to the clipboard fails in system status report. + += 2.5.3 - 01/03/2016 = +* Fix - Correct the 'unavailable template' call for variations so the message is displayed correctly, fixing a JS error. +* Fix - Add 'media-models' dependency to write panel scripts. +* Fix - Fix hide empty check in category walkers. +* Fix - Current class fix on some servers when empty. +* Fix - Multibyte safe trim string function. +* Fix - Prevent a notice by stopping a loop in woocommerce_products_will_display from stomping on other variables. +* Fix - If an attribute meta key is not set, technically its 'any', so should match. Prevents issues when meta data is missing after renaming attributes. +* Fix - Make wc_get_product_variation_attributes ignore non variation attributes. +* Fix - Notice when no order notes exist. +* Fix - Removed extra tab from plain email shipping address. +* Fix - Round shipping after tax calculation instead of before to prevent wrong taxes being calculated. +* Fix - State input box was not reappearing when switching from a hidden input to a text input. +* Fix - Don't duplicate rating and review counts. +* Fix - CLI - Allow setting of a single category. +* Fix - API - Replace term_taxonomy_id for term_id whilst creating/editing terms. +* Fix - API - Fix parent_id and menu_order for variations. +* Fix - Combine update post calls when update_status is ran. +* Fix - Total number of comments in the admin panel. +* Tweak - Show customer details for logged in users only on thanks page to prevent customer details being revealed if someone finds out the URL. +* Tweak - Wrap status report in backticks to stop people breaking .org forums. +* Tweak - Error handling for screen ids. +* Tweak - Use $wpdb->replace instead of doing a select and then deciding to do an update or insert in session handler. +* Tweak - Added check for private WooCommerce pages in status report. +* Tweak - Transactional emails for failed -> on hold. +* Dev - Include new triggers when removing and adding the password strength meter. +* Dev - Allow pass objects and arrays as webhook callbacks. + += 2.5.2 - 01/02/2016 = +* Fix - Compatibility with w3 total cache inline minification. +* Fix - Remove stock bw compat code which was preventing manage stock being disabled at variation level. +* Fix - When calculating shipping total, force rounding. +* Fix - Make save button clickable in tax rate table after using autocomplete field. +* Fix - Fix passed image_size variable in email templates. +* Fix - Don't show purchase note to admin in emails. +* Fix - Fix 'hide empty' setting in category widget . +* Fix - Prevent notice in get_allowed_countries. +* Fix - Prevent add-to-cart querystring in pagination links. +* Tweak - Allow propagation in variation script. +* Tweak - Product image alt text. +* Tweak - Remove notice and add styling for add payment page. +* Tweak - Set input margin and label display for compatibility with themes using bootstrap CSS. +* Tweak - Add context to category term localization. +* Tweak - Moved cart URL functions to core-functions file to make them available in admin area. +* Tweak - Added password hint text and error messages when showing the password strength meter in forms. +* Tweak - Added Saudi Riyal currency. +* Tweak - Added Russian Ruble symbol. +* Tweak - When COOKIEPATH is an empty string, set to '/' so cookies work across all pages. +* Dev - Template - Pass $category into wc_product_cat_class() in content-product_cat.php + += 2.5.1 - 25/01/2016 = +* Fix - Remove usage of get_currentuserinfo() which is deprecated in WordPress 4.5. +* Fix - Fix responsive product sizes when the columns class is missing. +* Fix - Fix function exists check for woocommerce_template_loop_category_title. +* Fix - check_version on all requests so that the installer runs after remote plugin updates. +* Fix - Only show the "add payment method" button when needed, and check for required fields on the add payment method page. +* Fix - Correctly block UI to prevent attribute issues in backend when adding multiple attributes in quick succession. +* Fix - Show SKU in admin emails. +* Fix - Don't show downloads in admin emails. +* Fix - Fix query/missing variable in validate_user_usage_limit function. +* Fix - Prevent endless loading on checkout when reload_checkout session variable was used. +* Fix - Correctly display html entities in tax screen autocomplete. +* Fix - Do sales reports based on refund line items rather than fully refunded orders to prevent double refunds being reported. +* Fix - Qty button can be hidden for variable products sold individually. +* Fix - Show the taxable country rather than base country in "estimated for" text during checkout. +* Fix - Prevent select2 gaining focus on IOS7 scroll. +* Fix - API - Fix indexes on decimal and thousand values. +* Tweak - Clear cron jobs on uninstall . +* Tweak - Don't disable place order button on checkout if a weak password is used. +* Tweak - Added password strength meter in lost password and edit accout pages. +* Tweak - Pass $args to woocommerce_dropdown_variation_attribute_options_html hook. + += 2.5.0 - 18/01/2016 = +* Feature - New default session handler. Uses custom table to store data rather than the options table for performance and scalability reasons. https://woocommerce.wordpress.com/2015/10/07/new-session-handler-in-2-5/ +* Feature - New tax settings UI - faster, enhanced with ajax, searchable. +* Feature - WP CLI Support. https://woocommerce.wordpress.com/2015/10/01/sneak-peek-wp-cli-support-in-woocommerce/ +* Feature - Added terms and conditions checkbox to pay page. +* Feature - Password strength indicators. +* Feature - Added 'pay' link to order screen. +* Feature - Added admin order/payment failed notification. +* Fix - Check for existence of global attribute when you get_attributes() for a product. +* Fix - Show order by template on product search. +* Fix - Search variation skus in backend search. +* Tweak - For coupons with category restrictions, respect the category hierarchy. +* Tweak - Added wc_array_cartesian function to generate variations in a logical order. +* Tweak - Revised email settings screens to show emails in a table and avoid a long sub-nav. +* Tweak - Default customer role capabilities. +* Tweak - Expire mini-cart cache after 24 hours. +* Tweak - Improved refund error messages in PayPal standard. +* Tweak - Removed language pack downloader in favour of translate.wordpress.org. +* Tweak - Added onboarding wizard button to the contextual help so it can be accessed again. +* Tweak - When a WordPress user is deleted, turn any orders they have into Guest orders. +* Tweak - When calculating order taxes, respect tax settings and default to base country. +* Tweak - Fade in variation images to avoid flicker during load. +* Tweak - Display 2 averages on report (net and gross). +* Tweak - Improve product search and use WPDB instead of several get_posts queries for performance. +* Tweak - Use SKU for stock order notes. +* Tweak - Added order notes for manual email sends. +* Tweak - Sanitize shipping method labels/titles. +* Tweak - Only display the coupon form on the checkout if a coupon hasn't been applied. +* Tweak - Added billing address column to order screen (off for new users). +* Tweak - Created function to disable author archives for customers. +* Tweak - When updating cart hash, refresh all open tabs. +* Tweak - Use new "question" mark icon font for help tips. +* Tweak - Improved review verification status retrieval. +* Tweak - Improve appearance when only 1 gateway is active. +* Tweak - Aligned terms box left and added required asterisk. +* Tweak - Removed dropdown display mode for cart shipping methods - radios are more flexible. +* Dev - API - Added /products/shipping_classes endpoint. +* Dev - API - Added support to POST, PUT, and DELETE categories and tags. +* Dev - API - Added support to filter products by tag, category, shipping class, and attribute. +* Dev - API - Added tax and tax_class endpoints. +* Dev - Template - New star ratings. The old one was 5 separate buttons. This new one consolidates the 5 options into one element making it leaner visually and more intuitive. Works in IE9+ with a graceful degradation for IE8. +* Dev - Template - Added `data-title` attribute to cart table. +* Dev - Template - Product archive anchors are now hooked into templates rather than hard coded. +* Dev - Template - Added template files for the customer details list in emails. emails/email-customer-details.php +* Dev - Template - Revised single variation cart template. Template files now exist for variations, and the cart button will display (disabled) when no selections are made. +* Dev - Template - Made "my orders" columns fully customizable with filters. +* Dev - Template - Unified email template order details tables to use a single template. +* Dev - Allow wc_clean to support arrays. +* Dev - Added a manual update trigger for checkout. +* Dev - Added woocommerce_is_price_filter_active filter to Query class. +* Dev - Replaced some cart methods with dedicated functions. e.g. wc_ship_to_billing_address_only(). +* Localisation - Add Kenyan currency and symbol. + += 2.4.13 - 11/01/2016 = +* Fix - Potential redirect loop when using 'unforce ssl' setting and a https home URL. +* Fix - Escape option names when cleaning up sessions. + += 2.4.12 - 9/12/2015 = +* Fix - 4.4 - Permission error when editing attribute terms. +* Fix - 4.4 - Missing variation images when wp_get_attachment_image_srcset() returns false instead of a string. +* Fix - 4.4 - Use post-thumbnail size in admin to avoid srcset. +* Fix - Webhook status not changed after save with active object-cache. + += 2.4.11 - 7/12/2015 = +* Fix - WordPress 4.4 support. +* Fix - Removes Switzerland from EU VAT definition . +* Fix - Fix auth endpoint urls. +* Fix - To allow backslash in SKUs. +* Fix - Sanity check for min/max quantity . +* Fix - 4.4 - Shipping class menu display. +* Fix - 4.4 - Admin menu icons and styling. +* Fix - API - Variable product backorders editing. +* Fix - API - Delete product transients when delete a variable product. +* Fix - API - Returned status when have an invalid oAuth timestamp. +* Fix - API - Early call of order status when editing orders. +* Tweak - 4.4 - Basic support for product embeds. +* Tweak - 4.4 - Support for srcset/sizes and responsive images. +* Tweak - 4.4 - Support for Twenty Sixteen. + = 2.4.10 - 10/11/2015 = * Fix - Geo IP - Correctly parse .dat files. * Fix - Geo IP - Ensure WC_Logger class exists before logging errors. diff --git a/Gruntfile.js b/Gruntfile.js index 9b68e9972f7..a5cb7009852 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -31,7 +31,8 @@ module.exports = function( grunt ) { // Minify .js files. uglify: { options: { - preserveComments: 'some' + // Preserve comments that start with a bang. + preserveComments: /^!/ }, admin: { files: [{ @@ -235,6 +236,12 @@ module.exports = function( grunt ) { 'css' ]); + grunt.registerTask( 'js', [ + 'jshint', + 'uglify:admin', + 'uglify:frontend' + ]); + grunt.registerTask( 'css', [ 'sass', 'cssmin' diff --git a/README.md b/README.md index fda8ca58c57..e9be6979f1b 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,20 @@ Welcome to the WooCommerce repository on GitHub. Here you can browse the source, If you are not a developer, please use the [WooCommerce plugin page](http://wordpress.org/plugins/woocommerce/) on WordPress.org. ## Documentation -* The [WooCommerce docs site](http://docs.woothemes.com/documentation/plugins/woocommerce/) -* [WooCommerce API Docs](http://docs.woothemes.com/wc-apidocs/) +* [WooCommerce Documentation](http://docs.woothemes.com/documentation/plugins/woocommerce/) +* [WooCommerce Knowledge Base](https://support.woothemes.com/hc/en-us/categories/200146917-WooCommerce) +* [WooCommerce Code Reference](http://docs.woothemes.com/wc-apidocs/) * [WooCommerce REST API Docs](http://woothemes.github.io/woocommerce-rest-api-docs/) ## Support This repository is not suitable for support. Please don't use our issue tracker for support requests, but for core WooCommerce issues only. Support can take place in the appropriate channels: * The [WooThemes premium support portal](http://support.woothemes.com/) for customers who have purchased themes or extensions. -* [Our public HelpDesk](https://support.woothemes.com/hc/communities/public/topics) which is available for all WooCommerce users. +* [Our community forum on wp.org](https://wordpress.org/support/plugin/woocommerce) which is available for all WooCommerce users. Support requests in issues on this repository will be closed on sight. ## Contributing to WooCommerce -If you have a patch, or stumbled upon an issue with WooCommerce core, you can contribute this back to the code. Please read our [contributor guidelines](https://github.com/woothemes/woocommerce/blob/master/CONTRIBUTING.md) for more information how you can do this. +If you have a patch, or stumbled upon an issue with WooCommerce core, you can contribute this back to the code. Please read our [contributor guidelines](https://github.com/woothemes/woocommerce/blob/master/.github/CONTRIBUTING.md) for more information how you can do this. If you have an idea for WooCommerce, see the [Roadmap Trello board](https://trello.com/b/YgRbpuze/woocommerce-roadmap). diff --git a/apigen.neon b/apigen.neon index aec9743d1bc..a1c00dd174f 100644 --- a/apigen.neon +++ b/apigen.neon @@ -29,7 +29,7 @@ main: WC title: WooCommerce 2.5.x Code Reference # base url used for sitemap (useful for public doc) -baseUrl: http://docs.woothemes.com/wc-apidocs/ +baseUrl: https://docs.woothemes.com/wc-apidocs/ # choose ApiGen template theme templateTheme: default diff --git a/apigen/hook-docs.php b/apigen/hook-docs.php index 5da84ac48e1..70808ca9771 100644 --- a/apigen/hook-docs.php +++ b/apigen/hook-docs.php @@ -122,6 +122,45 @@ class WC_HookFinder { case 'filter' : case 'action' : $hook = trim( $token[1], "'" ); + $loop = 0; + + if ( '_' === substr( $hook, '-1', 1 ) ) { + $hook .= '{'; + $open = true; + // Keep adding to hook until we find a comma or colon + while ( 1 ) { + $loop ++; + $next_hook = trim( trim( is_string( $tokens[ $index + $loop ] ) ? $tokens[ $index + $loop ] : $tokens[ $index + $loop ][1], '"' ), "'" ); + + if ( in_array( $next_hook, array( '.', '{', '}', '"', "'", ' ' ) ) ) { + continue; + } + + $hook_first = substr( $next_hook, 0, 1 ); + $hook_last = substr( $next_hook, -1, 1 ); + + if ( in_array( $next_hook, array( ',', ';' ) ) ) { + if ( $open ) { + $hook .= '}'; + $open = false; + } + break; + } + + if ( '_' === $hook_first ) { + $next_hook = '}' . $next_hook; + $open = false; + } + + if ( '_' === $hook_last ) { + $next_hook .= '{'; + $open = true; + } + + $hook .= $next_hook; + } + } + if ( isset( self::$custom_hooks_found[ $hook ] ) ) { self::$custom_hooks_found[ $hook ]['file'][] = self::$current_file; } else { @@ -169,13 +208,13 @@ class WC_HookFinder { echo '
").css({top:c-16,left:b+20}).appendTo("body").fadeIn(200)}var c=null,d=null;a(".chart-placeholder").bind("plothover",function(e,f,g){if(g){if((c!==g.dataIndex||d!==g.seriesIndex)&&(c=g.dataIndex,d=g.seriesIndex,a(".chart-tooltip").remove(),g.series.points.show||g.series.enable_tooltip)){var h=g.series.data[g.dataIndex][1],i="";g.series.prepend_label&&(i=i+g.series.label+": "),g.series.prepend_tooltip&&(i+=g.series.prepend_tooltip),i+=h,g.series.append_tooltip&&(i+=g.series.append_tooltip),g.series.pie.show?b(f.pageX,f.pageY,i):b(g.pageX,g.pageY,i)}}else a(".chart-tooltip").remove(),c=null}),a(".wc_sparkline.bars").each(function(){var b=a(this).data("sparkline"),c={grid:{show:!1}},d=[{data:b,color:a(this).data("color"),bars:{fillColor:a(this).data("color"),fill:!0,show:!0,lineWidth:1,barWidth:a(this).data("barwidth"),align:"center"},shadowSize:0}];a.plot(a(this),d,c)}),a(".wc_sparkline.lines").each(function(){var b=a(this).data("sparkline"),c={grid:{show:!1}},d=[{data:b,color:a(this).data("color"),lines:{fill:!1,show:!0,lineWidth:1,align:"center"},shadowSize:0}];a.plot(a(this),d,c)});var e=a(".range_datepicker").datepicker({changeMonth:!0,changeYear:!0,defaultDate:"",dateFormat:"yy-mm-dd",numberOfMonths:1,maxDate:"+0D",showButtonPanel:!0,showOn:"focus",buttonImageOnly:!0,onSelect:function(b){var c=a(this).is(".from")?"minDate":"maxDate",d=a(this).data("datepicker"),f=a.datepicker.parseDate(d.settings.dateFormat||a.datepicker._defaults.dateFormat,b,d.settings);e.not(this).datepicker("option",c,f)}}),f=document.createElement("a");"undefined"==typeof f.download&&a(".export_csv").hide(),a(".export_csv").click(function(){var b=a(this).data("exclude_series")||"";b=b.toString(),b=b.split(",");var c,d,e,f=a(this).data("xaxes"),g=a(this).data("groupby"),h=a(this).data("export"),i="data:application/csv;charset=utf-8,";if("table"===h)a(this).closest("div").find("thead tr,tbody tr").each(function(){a(this).find("th, td").each(function(){var b=a(this).text();b=b.replace("[?]",""),i+='"'+b+'",'}),i=i.substring(0,i.length-1),i+="\n"}),a(this).closest("div").find("tfoot tr").each(function(){a(this).find("th, td").each(function(){var b=a(this).text();if(b=b.replace("[?]",""),i+='"'+b+'",',a(this).attr("colspan")>0)for(m=1;m 0 ? '&' : '?' ) + 'action=woocommerce_tax_rates_save_changes', + data: { + current_class: data.current_class, + wc_tax_nonce: data.wc_tax_nonce, + changes: self.changes + }, + success: function( response, textStatus ) { + if ( 'success' === textStatus ) { + WCTaxTableModelInstance.set( 'rates', response.data.rates ); + WCTaxTableModelInstance.trigger( 'change:rates' ); + + WCTaxTableModelInstance.changes = {}; + WCTaxTableModelInstance.trigger( 'saved:rates' ); + + // Reload view. + WCTaxTableInstance.render(); + } + + self.unblock(); + } + }); } } ), WCTaxTableViewConstructor = Backbone.View.extend({ @@ -91,7 +119,7 @@ this.listenTo( this.model, 'change:rates', this.setUnloadConfirmation ); this.listenTo( this.model, 'saved:rates', this.clearUnloadConfirmation ); - $tbody.on( 'change', { view: this }, this.updateModelOnChange ); + $tbody.on( 'change autocompletechange', ':input', { view: this }, this.updateModelOnChange ); $tbody.on( 'sortupdate', { view: this }, this.updateModelOnSort ); $search_field.on( 'keyup search', { view: this }, this.onSearchField ); $pagination.on( 'click', 'a', { view: this }, this.onPageChange ); @@ -150,6 +178,9 @@ current_page: this.page, qty_pages: qty_pages } ) ); + } else { + $pagination.empty(); + view.page = 1; } // Disable sorting if there is a search term filtering the items. @@ -220,6 +251,8 @@ return parseInt( val, 10 ); } ); + // Move the last page + view.page = view.qty_pages; } rates[ newRow.tax_rate_id ] = newRow; @@ -235,27 +268,13 @@ model = view.model, rates = _.indexBy( model.get( 'rates' ), 'tax_rate_id' ), changes = {}, - $current, current_id, current_order, rates_to_reorder, reordered_rates; + $current, current_id; event.preventDefault(); if ( $current = $tbody.children( '.current' ) ) { $current.each(function(){ current_id = $( this ).data('id'); - current_order = parseInt( rates[ current_id ].tax_rate_order, 10 ); - - rates_to_reorder = _.filter( rates, function( rate ) { - if ( parseInt( rate.tax_rate_order, 10 ) > current_order ) { - return true; - } - return false; - } ); - - reordered_rates = _.map( rates_to_reorder, function( rate ) { - rate.tax_rate_order--; - changes[ rate.tax_rate_id ] = _.extend( changes[ rate.tax_rate_id ] || {}, { tax_rate_order : rate.tax_rate_order } ); - return rate; - } ); delete rates[ current_id ]; @@ -345,53 +364,29 @@ model.setRateAttribute( id, attribute, val ); }, - updateModelOnSort: function( event, ui ) { + updateModelOnSort: function( event ) { var view = event.data.view, model = view.model, - $tr = ui.item, - tax_rate_id = $tr.data( 'id' ), rates = _.indexBy( model.get( 'rates' ), 'tax_rate_id' ), - old_position = rates[ tax_rate_id ].tax_rate_order, - new_position = $tr.index() + ( ( view.page - 1 ) * view.per_page ), - which_way = ( new_position > old_position ) ? 'higher' : 'lower', - changes = {}, - rates_to_reorder, reordered_rates; + changes = {}; - rates_to_reorder = _.filter( rates, function( rate ) { - var order = parseInt( rate.tax_rate_order, 10 ), - limits = [ old_position, new_position ]; + _.each( rates, function( rate ) { + var new_position = 0; + var old_position = parseInt( rate.tax_rate_order, 10 ); - if ( parseInt( rate.tax_rate_id, 10 ) === parseInt( tax_rate_id, 10 ) ) { - return true; - } else if ( order > _.min( limits ) && order < _.max( limits ) ) { - return true; - } else if ( 'higher' === which_way && order === _.max( limits ) ) { - return true; - } else if ( 'lower' === which_way && order === _.min( limits ) ) { - return true; - } - return false; - } ); - - reordered_rates = _.map( rates_to_reorder, function( rate ) { - var order = parseInt( rate.tax_rate_order, 10 ); - - if ( parseInt( rate.tax_rate_id, 10 ) === parseInt( tax_rate_id, 10 ) ) { - rate.tax_rate_order = new_position; - } else if ( 'higher' === which_way ) { - rate.tax_rate_order = order - 1; - } else if ( 'lower' === which_way ) { - rate.tax_rate_order = order + 1; + if ( $table.find( 'tr[data-id="' + rate.tax_rate_id + '"]').length ) { + new_position = parseInt( $table.find( 'tr[data-id="' + rate.tax_rate_id + '"]').index(), 10 ) + parseInt( ( view.page - 1 ) * view.per_page, 10 ); + } else { + new_position = old_position; } - changes[ rate.tax_rate_id ] = _.extend( changes[ rate.tax_rate_id ] || {}, { tax_rate_order : rate.tax_rate_order } ); - - return rate; + if ( old_position !== new_position ) { + changes[ rate.tax_rate_id ] = _.extend( changes[ rate.tax_rate_id ] || {}, { tax_rate_order : new_position } ); + } } ); - if ( reordered_rates.length ) { + if ( _.size( changes ) ) { model.logChanges( changes ); - view.render(); // temporary, probably should get yanked. } }, sanitizePage: function( page_num ) { @@ -409,8 +404,6 @@ } ), WCTaxTableInstance = new WCTaxTableViewConstructor({ model: WCTaxTableModelInstance, - // page: data.page, // I'd prefer to have these two specified down here in the instance, - // per_page: data.limit, // but it doesn't seem to recognize them in render if I do. :\ el: '#rates' } ); diff --git a/assets/js/admin/settings-views-html-settings-tax.min.js b/assets/js/admin/settings-views-html-settings-tax.min.js index a4e3170e5f8..7c4e185bcd1 100644 --- a/assets/js/admin/settings-views-html-settings-tax.min.js +++ b/assets/js/admin/settings-views-html-settings-tax.min.js @@ -1 +1 @@ -!function(a,b,c,d){a(function(){String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")});var e=c.template("wc-tax-table-row"),f=c.template("wc-tax-table-row-empty"),g=c.template("wc-tax-table-pagination"),h=a(".wc_tax_rates"),i=a("#rates"),j=a('input[name="save"]'),k=a("#rates-pagination"),l=a("#rates-search .wc-tax-rates-search-field"),m=a(".submit .button-primary[type=submit]"),n=Backbone.Model.extend({changes:{},setRateAttribute:function(a,b,c){var d=_.indexBy(this.get("rates"),"tax_rate_id"),e={};d[a][b]!==c&&(e[a]={},e[a][b]=c,d[a][b]=c),this.logChanges(e)},logChanges:function(a){var b=this.changes||{};_.each(a,function(a,c){b[c]=_.extend(b[c]||{tax_rate_id:c},a)}),this.changes=b,this.trigger("change:rates")},getFilteredRates:function(){var a=this.get("rates"),b=l.val().toLowerCase();return b.length&&(a=_.filter(a,function(a){var c=_.toArray(a).join(" ").toLowerCase();return-1!==c.indexOf(b)})),a=_.sortBy(a,function(a){return parseInt(a.tax_rate_order,10)})},save:function(){a.post(d+"?action=woocommerce_tax_rates_save_changes",{current_class:b.current_class,wc_tax_nonce:b.wc_tax_nonce,changes:this.changes},this.onSaveResponse,"json")},onSaveResponse:function(a,b){"success"===b&&(p.set("rates",a.data.rates),p.trigger("change:rates"),p.changes={},p.trigger("saved:rates"))}}),o=Backbone.View.extend({rowTemplate:e,per_page:b.limit,page:b.page,initialize:function(){var c=Math.ceil(_.toArray(this.model.get("rates")).length/this.per_page);this.qty_pages=0===c?1:c,this.page=this.sanitizePage(b.page),this.listenTo(this.model,"change:rates",this.setUnloadConfirmation),this.listenTo(this.model,"saved:rates",this.clearUnloadConfirmation),i.on("change",{view:this},this.updateModelOnChange),i.on("sortupdate",{view:this},this.updateModelOnSort),l.on("keyup search",{view:this},this.onSearchField),k.on("click","a",{view:this},this.onPageChange),k.on("change","input",{view:this},this.onPageChange),a(window).on("beforeunload",{view:this},this.unloadConfirmation),m.on("click",{view:this},this.onSubmit),j.attr("disabled","disabled"),h.find(".insert").on("click",{view:this},this.onAddNewRow),h.find(".remove_tax_rates").on("click",{view:this},this.onDeleteRow),h.find(".export").on("click",{view:this},this.onExport)},render:function(){var c=this.model.getFilteredRates(),d=_.size(c),e=Math.ceil(d/this.per_page),h=0===d?0:this.per_page*(this.page-1),j=this.per_page*this.page,m=_.toArray(c).slice(h,j),n=this;this.$el.empty(),m.length?a.each(m,function(a,b){n.$el.append(n.rowTemplate(b))}):n.$el.append(f()),this.$el.find("td.country input").autocomplete({source:b.countries,minLength:2}),this.$el.find("td.state input").autocomplete({source:b.states,minLength:3}),this.$el.find("td.postcode input, td.city input").change(function(){a(this).attr("name",a(this).data("name"))}),e>1&&k.html(g({qty_rates:d,current_page:this.page,qty_pages:e})),l.val()?i.sortable("disable"):i.sortable("enable")},updateUrl:function(){if(window.history.replaceState){var a=b.base_url,c=l.val();1' + value + '
'; + } ); + error_html = error_html + '"+b+"
"}),c+="' + description + '
' ); + $( this ).closest( 'article' ).height( $( this ).parent().height() ); + } + } ), + shippingZone = new ShippingZone({ + zones: data.zones + } ), + shippingZoneView = new ShippingZoneView({ + model: shippingZone, + el: $tbody + } ); + + shippingZoneView.render(); + + $tbody.sortable({ + items: 'tr', + cursor: 'move', + axis: 'y', + handle: 'td.wc-shipping-zone-sort', + scrollSensitivity: 40 + }); + + function getEnhancedSelectFormatString() { + var formatString = { + formatMatches: function( matches ) { + if ( 1 === matches ) { + return wc_enhanced_select_params.i18n_matches_1; + } + return wc_enhanced_select_params.i18n_matches_n.replace( '%qty%', matches ); + }, + formatNoMatches: function() { + return wc_enhanced_select_params.i18n_no_matches; + }, + formatAjaxError: function() { + return wc_enhanced_select_params.i18n_ajax_error; + }, + formatInputTooShort: function( input, min ) { + var number = min - input.length; + + if ( 1 === number ) { + return wc_enhanced_select_params.i18n_input_too_short_1; + } + + return wc_enhanced_select_params.i18n_input_too_short_n.replace( '%qty%', number ); + }, + formatInputTooLong: function( input, max ) { + var number = input.length - max; + + if ( 1 === number ) { + return wc_enhanced_select_params.i18n_input_too_long_1; + } + + return wc_enhanced_select_params.i18n_input_too_long_n.replace( '%qty%', number ); + }, + formatSelectionTooBig: function( limit ) { + if ( 1 === limit ) { + return wc_enhanced_select_params.i18n_selection_too_long_1; + } + + return wc_enhanced_select_params.i18n_selection_too_long_n.replace( '%qty%', limit ); + }, + formatLoadMore: function() { + return wc_enhanced_select_params.i18n_load_more; + }, + formatSearching: function() { + return wc_enhanced_select_params.i18n_searching; + } + }; + + return formatString; + } + }); +})( jQuery, shippingZonesLocalizeScript, wp, ajaxurl ); diff --git a/assets/js/admin/wc-shipping-zones.min.js b/assets/js/admin/wc-shipping-zones.min.js new file mode 100644 index 00000000000..e89f2c3b156 --- /dev/null +++ b/assets/js/admin/wc-shipping-zones.min.js @@ -0,0 +1 @@ +!function(a,b,c,d){a(function(){function e(){var a={formatMatches:function(a){return 1===a?wc_enhanced_select_params.i18n_matches_1:wc_enhanced_select_params.i18n_matches_n.replace("%qty%",a)},formatNoMatches:function(){return wc_enhanced_select_params.i18n_no_matches},formatAjaxError:function(){return wc_enhanced_select_params.i18n_ajax_error},formatInputTooShort:function(a,b){var c=b-a.length;return 1===c?wc_enhanced_select_params.i18n_input_too_short_1:wc_enhanced_select_params.i18n_input_too_short_n.replace("%qty%",c)},formatInputTooLong:function(a,b){var c=a.length-b;return 1===c?wc_enhanced_select_params.i18n_input_too_long_1:wc_enhanced_select_params.i18n_input_too_long_n.replace("%qty%",c)},formatSelectionTooBig:function(a){return 1===a?wc_enhanced_select_params.i18n_selection_too_long_1:wc_enhanced_select_params.i18n_selection_too_long_n.replace("%qty%",a)},formatLoadMore:function(){return wc_enhanced_select_params.i18n_load_more},formatSearching:function(){return wc_enhanced_select_params.i18n_searching}};return a}var f=a(".wc-shipping-zones"),g=a(".wc-shipping-zone-rows"),h=a(".wc-shipping-zone-save"),i=c.template("wc-shipping-zone-row"),j=c.template("wc-shipping-zone-row-blank"),k=a.extend({minimumResultsForSearch:10,allowClear:!!a(this).data("allow_clear"),placeholder:a(this).data("placeholder"),matcher:function(a,b,c){return b.toUpperCase().indexOf(a.toUpperCase())>=0||c.attr("alt").toUpperCase().indexOf(a.toUpperCase())>=0}},e()),l=Backbone.Model.extend({changes:{},logChanges:function(a){var b=this.changes||{};_.each(a,function(a,c){b[c]=_.extend(b[c]||{zone_id:c},a)}),this.changes=b,this.trigger("change:zones")},discardChanges:function(a){var b=this.changes||{},c=null,d=_.indexBy(this.get("zones"),"zone_id");b[a]&&void 0!==b[a].zone_order&&(c=b[a].zone_order),delete b[a],null!==c&&d[a]&&d[a].zone_order!==c&&(b[a]=_.extend(b[a]||{},{zone_id:a,zone_order:c})),this.changes=b,0===_.size(this.changes)&&o.clearUnloadConfirmation()},save:function(){_.size(this.changes)?a.post(d+(d.indexOf("?")>0?"&":"?")+"action=woocommerce_shipping_zones_save_changes",{wc_shipping_zones_nonce:b.wc_shipping_zones_nonce,changes:this.changes},this.onSaveResponse,"json"):n.trigger("saved:zones")},onSaveResponse:function(a,c){"success"===c&&(a.success?(n.set("zones",a.data.zones),n.trigger("change:zones"),n.changes={},n.trigger("saved:zones")):window.alert(b.strings.save_failed))}}),m=Backbone.View.extend({rowTemplate:i,initialize:function(){this.listenTo(this.model,"change:zones",this.setUnloadConfirmation),this.listenTo(this.model,"saved:zones",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:zones",this.render),g.on("change",{view:this},this.updateModelOnChange),g.on("sortupdate",{view:this},this.updateModelOnSort),a(window).on("beforeunload",{view:this},this.unloadConfirmation),h.on("click",{view:this},this.onSubmit),a(document.body).on("click",".add_shipping_method:not(.disabled)",{view:this},this.onAddShippingMethod),a(document.body).on("click",".wc-shipping-zone-add",{view:this},this.onAddNewRow),a(document.body).on("click",".wc-shipping-zone-save-changes",{view:this},this.onSubmit),a(document.body).on("wc_backbone_modal_response",this.onAddShippingMethodSubmitted),a(document.body).on("change",".wc-shipping-zone-method-selector select",this.onChangeShippingMethodSelector)},block:function(){a(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){a(this.el).unblock()},render:function(){var b=_.indexBy(this.model.get("zones"),"zone_id"),c=this;c.$el.empty(),c.unblock(),_.size(b)?(b=_.sortBy(b,function(a){return parseInt(a.zone_order,10)}),a.each(b,function(a,b){c.renderRow(b)})):c.$el.append(j),c.initRows()},renderRow:function(a){var b=this;b.$el.append(b.rowTemplate(a)),b.initRow(a)},initRow:function(a){var b=this,c=b.$el.find('tr[data-id="'+a.zone_id+'"]');_.each(a.zone_locations,function(a){if("string"===jQuery.type(a))c.find('option[value="'+a+'"]').prop("selected",!0);else if("postcode"===a.type){var b=c.find(".wc-shipping-zone-postcodes :input");b.val()?b.val(b.val()+"\n"+a.code):b.val(a.code),c.find(".wc-shipping-zone-postcodes").show(),c.find(".wc-shipping-zone-postcodes-toggle").hide()}else c.find('option[value="'+a.type+":"+a.code+'"]').prop("selected",!0)}),a.zone_postcodes&&_.each(a.zone_postcodes,function(a){var b=c.find(".wc-shipping-zone-postcodes :input");b.val()?b.val(b.val()+"\n"+a.code):b.val(a.code),c.find(".wc-shipping-zone-postcodes").show(),c.find(".wc-shipping-zone-postcodes-toggle").hide()}),b.renderShippingMethods(a.zone_id,a.shipping_methods),c.find(".view").show(),c.find(".edit").hide(),c.find(".wc-shipping-zone-edit").on("click",{view:this},this.onEditRow),c.find(".wc-shipping-zone-cancel-edit").on("click",{view:this},this.onCancelEditRow),c.find(".wc-shipping-zone-delete").on("click",{view:this},this.onDeleteRow),c.find(".wc-shipping-zone-postcodes-toggle").on("click",{view:this},this.onTogglePostcodes),!0===a.editing&&(c.addClass("editing"),c.find(".wc-shipping-zone-edit").trigger("click"))},initRows:function(){0===a("tbody.wc-shipping-zone-rows tr").length%2?f.find("tbody.wc-shipping-zone-rows").next("tbody").find("tr").addClass("odd"):f.find("tbody.wc-shipping-zone-rows").next("tbody").find("tr").removeClass("odd"),a("#tiptip_holder").removeAttr("style"),a("#tiptip_arrow").removeAttr("style"),a(".tips").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:50})},renderShippingMethods:function(b,c){var d=a('.wc-shipping-zones tr[data-id="'+b+'"]'),e=d.find(".wc-shipping-zone-methods ul");e.find(".wc-shipping-zone-method").remove(),_.size(c)?_.each(c,function(a,b){var c="method_disabled";"yes"===a.enabled&&(c="method_enabled"),e.prepend(''+b+"
"),a(this).closest("article").height(a(this).parent().height())}}),n=new l({zones:b.zones}),o=new m({model:n,el:g});o.render(),g.sortable({items:"tr",cursor:"move",axis:"y",handle:"td.wc-shipping-zone-sort",scrollSensitivity:40})})}(jQuery,shippingZonesLocalizeScript,wp,ajaxurl); \ No newline at end of file diff --git a/assets/js/admin/woocommerce_admin.js b/assets/js/admin/woocommerce_admin.js index be14474be02..9059a6219ce 100644 --- a/assets/js/admin/woocommerce_admin.js +++ b/assets/js/admin/woocommerce_admin.js @@ -7,10 +7,11 @@ jQuery( function ( $ ) { // Field validation error tips $( document.body ) + .on( 'wc_add_error_tip', function( e, element, error_type ) { var offset = element.position(); - if ( element.parent().find( '.wc_error_tip' ).size() === 0 ) { + if ( element.parent().find( '.wc_error_tip' ).length === 0 ) { element.after( '