Product features spec.

Posts: 4700
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

Well, this idea originated in Simon's session at the Drupalcon. It's not fully fleshed out and will certainly be updated in future releases, but we're getting to the point where contributed modules need a good way to assign features to products on a per product basis. These are things like a role assignment, a file download, a gift certificate, etc. In order to facilitate this, I propose the following...

Add a new tab (local task) to the product node edit form called features. This page is essentially a form that other modules can build into. Third party modules let the product module know they want to add something to the field with hook_product_feature(). This hook defines features in the following way:

<?php
function uc_role_product_feature() {
 
$features[] = array(
   
'id' => 'role',
   
'title' => t('Role assignment'),
   
'callback' => 'uc_role_feature_handler',
   
'settings' => 'uc_role_settings',
  );
}
?>

The id is naturally just an internal id. However, the title here represents the title of the fieldset. The callback is to some function in the module that will be used to handle adding elements to the form, validating, and submitting the data. The module need not implement every $op. It would look something like this:

<?php
function uc_role_feature_handler($op, $arg1) {
  switch (
$op) {
    case
'form':
     
// Define forms elements here.
     
return $form;
    case
'validate':
     
// Make sure data is valid.
     
if ($arg1['some_field'] == 'bad') {
       
form_set_error('some_field', t('Some field is bad!'));
      }
      break;
    case
'submit':
     
// Save the data on submission.
     
db_query("UPDATE {uc_role_table} SET field = '%s' WHERE role_id = %d", $arg1['some_field'], arg(1));
      break;
  }
}
?>

We can extend this as each case requires. Please note that functions can add a #theme field to their form elements to theme their fieldsets into tables or whatever else the case may require.

This will provide us with a central page for all related modules to add features to products. I propose that the tab should not show up if no module currently implements a feature. It would just be confusing. I'll leave it up to Lyle to implement that either by returning no display data or invoking the hook in the hook_menu() in uc_product.module (only when arg(0) == 'node' and arg(2) == 'edit'!).

If a product feature needs to define settings, the place to do this will be on a tab of the product settings form. This again is a local task beneath the path admin/store/settings/products/edit. This form functions much the same way the product features form does. It invokes hook_product_feature(), looks for any features w/ a settings key, and then populates the form using the same form, validate, and submit ops.

Modules that implement product features will also need to work out for themselves what happens when someone purchases that product. The way to do this is to use hook_order() with the update $op to see if an order has moved from in_checkout to post_checkout. (This has changed for Alpha 7d, so I'll be posting docs soon.) You can scan the products on an order to see if any implement a certain feature or not. Maybe this is overkill, though... maybe we should think about facilitating this somehow? This might be a good use of the data array for products added to carts, you know. Eye-wink

Any ideas, suggestions, or doomsaying?