Drupal Association members fund grants that make connections all over the world.
Drupal Commerce 1.2 represents the efforts of 25 credited contributors and many others who reported bugs and usability improvements and helped test the solutions. This release primarily improves Drupal Commerce's performance and usability while including a variety of minor bug fixes, API improvements, and a minor security fix as described in SA-CONTRIB-2012-014 - Drupal Commerce - Cross Site Scripting (XSS).
Read on for a brief description of the changes since Drupal Commerce 1.1, notes on updating from previous versions, and a full change log of commits.
Drupal Commerce 1.2 includes some key performance improvements contributed by a few developers optimizing it for use on sites with transaction volumes reaching into the tens of thousands per day. These improvements include the introduction of a few static caches and checks to prevent unnecessary processing in the following areas:
- Currency formatting
- Recalculation of product prices in the shopping cart refresh
- Rendering of product fields injected into display nodes
Performance improvements also came in the form of new database indexes and a compound index to a variety of tables, particularly in conjunction with the foreign key declarations made in hook_schema() arrays for our tables. It was possible before in high performance scenarios for database deadlocks to occur because of collisions on revision columns when orders were being saved concurrently, so a fix was committed involving using NULL for these columns to mitigate the unique value restrictions.
Drupal Commerce 1.2 includes many fixes to the default Views and a few configuration forms to simplify the on-site administration of customer profiles, products, and orders. Nearly every default View was changed in some way, with the most notable changes being the addition of exposed filters to help administrators find the items they're looking for in the Views. Additionally, we added a "Shopping carts" tab to the primary Orders View so store administrators will be able to locate shopping cart orders and orders in checkout without having to remove the default filter on the primary Orders View.
This release also brings the addition of product revision support, displayed on product edit forms in a "Change history" fieldset. This is the first step toward undoing accidental changes to product data, as every change can now be saved in a separate revision for future browsing and reversion.
Developer experience (DX) Improvements
Developers will be delighted to note the following improvements:
- We completed the documentation of all the hooks defined by the Commerce modules or invoked in conjunction with Rules events in our .api.php files.
- We consolidated our CSS files into .base.css, .admin.css, and .theme.css files (a.k.a. BAT notation) to help themers find and target the CSS rules they want to override.
- Uninstallation has been brought up to date to conform to changes in Drupal 7.4+ and support reinstallation on the same database if necessary (still not recommended).
- The Views form methods were removed from the line item summary area handler, so it no longer triggers the Views form build process; instead we implemented a workaround to reorder Commerce area handlers with respect to Views form submit buttons, which was the only reason we used the form methods instead of the normal render methods before.
Updating from previous versions
As always, updates should be tested in a non-production environment. Backup your files and database before putting Drupal Commerce 1.2 on it and running update.php. This new release involves a few updates to the database schema to add indexes and a new product revision table, and it includes a batch process to create the initial revisions for all of the products on your site. This process may take a while sites with large product catalogs, as it iterates over 50 products at a time performing an INSERT and an UPDATE query for each product.
Sites with custom modules may need to take into consideration two minor API changes:
- In a couple areas, such as tax rate and product reference select lists, we were sanitizing the values of the #options array in our form builder functions. However, the Forms API already sanitizes these values... but it only does it for select list form elements. If your module is altering a select list form element and changing its type (e.g. to a radios or checkboxes element), you are now responsible for sanitizing the values of the #options array in your alter function.
- hook_commerce_cart_order_is_cart() has been marked deprecated in favor of the new hook_commerce_cart_order_is_cart_alter() and will be removed in future versions.
From a site configuration standpoint, you now have the ability to enable product revisions by default (or not) on the product type configuration form. By default all product types will default to creating new revisions when edited via the UI.
Additionally, the changes to the default Views will not go into effect if you have already customized your Views. They amounted to adjusting some default sorts, adding exposed filters, and adding a "Shopping carts" tab to the Orders View. None are essential, but they do make on-site administration of customer profiles, products, and orders easier. If you have customized your Views, you would need to manually add these features to your Views or reset your Views and then recreate your changes on them.
Notes on the security announcement
Sites using Drupal Commerce 1.1 that gave product creation permissions to non-trusted users (e.g. marketplaces or multi-seller stores) may be vulnerable to cross site scripting as described in the security announcement.
This is only a problem if the site uses product display nodes that include the title or SKU of the referenced product in the node display through the Product Reference module's field injection feature. These sites must be updated to Drupal Commerce 1.2... but with all the good features packed in here, there's no reason for anyone to stay on 1.1. : )
Changes since 7.x-1.1 (73 commits):
- #1207242 by rfay, rszrama: fix the product form submission routine to check the access type on the revision checkbox when determining whether or not to create a new revision.
- #1362412 by rszrama: remove an unnecessary check on an order's uid in the checkout access function so redirected payment methods will properly handle the return of anonymous customers when a payment notification has already been received and processed, causing a user to be created and associated with the order.
- Reset the default Rules when a payment method module is enabled.
- Implement preprocess hooks for the product SKU and title templates to sanitize SKUs and titles at that point instead of when the theme function is called.
- #1352774 by das-peter, amateescu: improve the performance of referenced product field injection by only rendering visible fields for the requested view mode.
- #1207242 by amateescu, skipyT, dpolant: add support for product revisions.
- Validate the order e-mail address when an edit form is submitted.
- #1256302 by bojanz, edmund.kwok: change the line item area summary handler back to a non-Views form rendering method and instead use a Views preprocess hook to rearrange Commerce area handlers in the footer with respect to the form submit buttons.
- #1219762 by dpolant, amateescu: add a Views filter handler for price amount columns so Views may include price filters that accept values in the appropriate major unit instead of the minor unit.
- #1029638 by mr.baileys, rszrama: create custom empty text area handlers for the Customers, Orders, and Products Views that create empty text messages with links to the various add forms and accommodate exposed filters returning no results, too.
- #1386816 by googletorp: rearrange and combine stylesheets for each module into .base.css, .admin.css, and .theme.css stylesheets for an improved theme experience.
- Do not sanitize the #options values of the select lists used to specify which View should be used in the cart contents pane settings and the line item reference field's display formatter settings.
- Do not sanitize the title of display inclusive tax rates when building the #options array for the select list altered onto product forms to input prices including the tax; it will be handled by form_select_options().
- Sanitize the display title of price components when the price field display formatter shows the breakdown of price components.
- #1331788 by dpolant: update the default checkout completion e-mail notification to use the [commerce-order:customer-url] token instead of building the URL in the message; deprecate the [commerce-order:url] token in favor of the more specific naming convention and add an admin-url token as well.
- #1403972 by bojanz, amateescu: implement hook_system_info_alter() in the Commerce module to workaround uninstallation changes in Drupal 7.4+, making uninstallation and reinstallation possible again.
- #1356958 by vasike: change the Tax module's implementation of hook_field_attach_load() to acknowledge the fact that field deletion will result in this hook being invoked without fully loading the entities passed in the parameter, requiring us to ensure field data exists before attempting to manipulate it.
- #1089328 by rszrama: do not double the sanitization of options list values for product reference field options when a select list widget is being used; same for product add menu items where we were double sanitizing product type titles.
- #1365202 by Fonant, willkaxu, rszrama: do not sanitize the #options values for the product selector element since the default type is a select list; the minor API change commented in-line is that if other modules are altering this element to a different form element type (like 'radios'), they are responsible for sanitizing the #options values, too.
- Fix a function name typo in the Order module.
- #1366976 by Damien Tournoud, mjpa, rszrama: allow hook_commerce_cart_order_id() to return FALSE indicating that the user does not have a valid cart order ID.
- #1322854 by Damien Tournoud, amateescu: minor API change - update hook_commerce_cart_order_is_cart() to allow modules to affirm an order is a cart instead of just deny it; also marked that hook as deprecated and added an alternate hook_commerce_cart_order_is_cart_alter() to be used instead.
- #1345052 by mr.baileys: avoid unnecessary product view mode creation for the view modes created via product reference field associations.
- #1402866 by amateescu: prevent notices in the Product Reference module's extra fields integration when there are no defined product types.
- #1260382 by amateescu: use the customer profile reference field instance name for related checkout pane to allow for retitling of customer profile checkout panes via the UI.
- #1274986 by amateescu: specify the proper access callback for the Rules event 'When an order is first paid in full' defined by the Payment module.
- #1363814 by bojanz, amateescu, Damien Tournoud: retain saved orders in the entity cache until the cache gets explicitly reset.
- #1363826 by Damien Tournoud, bojanz, amateescu: change the revision_id and order_number columns in the commerce_order table and order_number in the commerce_order_revision table to support NULL values to avoid database deadlocks when orders are inserted concurrently (caused by the UNIQUE constraint on the order_number column).
- #1408664 by bojanz: update the status property for products to be a boolean in its entity property info declaration.
- Fix the type column name for the uid_by_type index on the commerce_customer_profile table.
- #1388868 by darrylh, rszrama: add indexes to the customer profile table, including a combined index on uid and type.
- Add indexes to the line item table for Order ID and line item type.
- #1403906 by serialjaywalker: add indexes to foreign key columns for products, orders, and payment transactions.
- #1377746 by amateescu: only refresh a shopping cart order object on load if it represents the latest revision of the order.
- #1403212 by mr.baileys: fix some entity property info declaration for the Customer profile and Product entities.
- #1404882 by my.baileys: remove an unnecessary check_plain() call in t() where a % placeholder is being used.
- Filter the line items View for orders to only show product line items by default.
- Update the default line items View used in the display formatter for the line item reference field attached to orders.
- Update the Order payments View and change its date display to Drupal's short format, which includes the time instead of just the date.
- Update the main Customers View and add an exposed filter to filter the View by customer name.
- Move the creation of the Shopping Carts tab on the main Orders View to the Cart module and remove entirely the alteration of the default View by the Checkout module; it was unnecessary, as the tab only needs to appear when the shopping cart is being used.
- Change the default sort on the customer Orders View to be the order number descending instead of the created timestamp.
- Add the product status to the main Products View and an include an exposed filter to search by SKU fragments.
- #1400242 by mr.baileys: remove check_plain() calls from within two drupal_set_title() calls; they are redundant.
- #1068940 by amateescu: fix a CSS problem and strict PHP notice with respect to embedding the 'View order' form in the Views area handler.
- #1230114 by googletorp: Allow to use raw values product type in Views.
- Fix the default sort on the admin Orders View and add a separate tab for Shopping cart / Checkout orders; make use of the new 'View order' form area handler in the View's header.
- #737810 by dpolant: add unit tests for Order CRUD and define order property info for the hostname column.
- #1397096 by mr.baileys: only show the checkbox to include a checkout pane in the review pane if the checkout pane defines a review callback.
- #1068940 by dpolant, rszrama: add a 'View order' form Views area handler that redirects to the specified order view page on submission.
- #1380394 by fibero: add support for Kazakhstani Tenge (KZT).
- #1380714 by Artusamak: add context to the credit card issue number string.
- #1380738 by Artusamak: add missing t() calls around machine name strings in overviews.
- #1377754 by rszrama: remove instances of rowCount() from queries that count items in the database.
- #1377812 by Dippers: fix the default display formatter for customer profile reference fields to a formatter that actually exists.
- #1363838 by Damien Tournoud: Don't reload every product one by one when refreshing cart orders, because we have other methods in place now to prevent the duplicate sell price calculation of loaded products.
- #1363808 by Damien Tournoud: store currency info in a static cache so we don't hit the DB cache multiple times.
- #1356006 by fago, pcambra, rszrama: fix the property info definition for our reference fields by removing some unnecessary code for product reference fields and leaving the fields' query callbacks intact.
- Fix the Payment transaction amount field handler to ensure the amount is converted to a decimal value on output.
- Reorder the Configuration menu item to always appear at the bottom of the Store menu with a weight of 50.
- #1371718 by seddonym: rename hook implementations inside the Payment module.
- #1365622 by noland: fix an if statement to use == instead of = when checking if a currency should be converted to a decimal value for formatting.
- Add a missing parameter to commerce_round() in the line item action 'Divide the unit price by some amount.'
- #1362774 by iswilson: fix the parameter check in commerce_line_items_total().
- Add missing documentation for all the remaining hooks invoked directly by all the Commerce modules and ensure all hooks are represented in the various modules' implementations of hook_hook_info().
- Add missing documentation for Commerce hooks.
- #1357364 by rszrama: add missing documentation for Product hooks.
- #1115994 by jeff.maes: set a high #maxlength back on the product reference textfield widget to get around Drupal's default maxlength on textfields.
- #1345890 by pcambra, rszrama: alter entity queries to allow querying on the non-existent state column by rewriting property conditions for state to look for statuses in the specified state.
- #1356186 by rszrama, dpolant: add missing documentation for Customer hooks.
- #1356202 by rszrama, dpolant: add missing documentation for Checkout hooks.
- #1356232 by dpolant: add missing hook documentation for the Payment module.
- #1356168 by dpolant: add missing hook documentation for the Order module.