a work on process

Viewing posts tagged: PHP

Extending drupal’s checkout process

18 February 2007 (9:33 am)

By James Stewart
Filed under: Snippets
Tagged: , , , , ,

In yesterday’s post on creating custom product types in drupal I promised a follow up on how we were adding the license generation to our checkout. I’m not going to go through all the steps in great detail as most of what I wrote is specific to our situation, and the custom PHP module (written in C) that generates our licenses, but it took me a while to work out how to hook in, so here are a few words.

In addition to our custom product type module ‘licensable’, I also wrote a module called ‘licenses’ which allows the site administrator to specify types of licenses to go with specific products and generate licenses, and for users to review the licenses they’ve bought through their account. It’s in that module that I connected with the transaction API to generate licenses after a purchase.

The callback in question is ‘hook_ec_transactionapi’ and we needed to intercept the ‘update’ operation:

function licenses_ec_transactionapi($txn, $op, $a3, $a4) {
    switch ($op) {
        case 'update':
            if ($txn->payment_status == 2) {
                licenses_generate_license($txn);
            }
            break;
    }
    return true;
}

A payment_status of 2 means that the payment has been completed and we can generate the license. The ‘licenses_generate_license’ function can then loop through the transaction’s products and generate licenses for any that are licensable. Some rough code for that would be:

function licenses_generate_license(&$transaction) {
  $user = user_load(array('uid' => $transaction->uid));
 
  foreach($transaction->items as &$product) {
    if ($product->ptype == 'licensable') {
      // generate license
    }
  }
 
  // send email to user with their license details
}

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

Custom product types in drupal

17 February 2007 (12:34 pm)

By James Stewart
Filed under: Snippets
Tagged: , , , , ,

For the Scodigo site we wanted to be able to sell licenses to use the SmartPill PHP Edition plugin. For the most part that just involves a standard ecommerce flow, and so we opted to use drupal’s suite of ecommerce modules, but we wanted to make some customizations along the way, such as being able to offer product variations (eg. different user counts for the licenses) and generating and emailing a license rather than shipping a product or delivering access to a file. To achieve that I created two custom modules: a product type called ‘licensable’ and a license management module creatively titled ‘licenses.’

I’m going to presume that anyone following along with this post is already familiar with building drupal modules. If you’re not I’d recommend starting with the module developer’s guide over on the drupal site. I’m also going to be writing about developing for drupal 4.7 with ecommerce 2.1.x as I’ve not had a chance to try this out in version 5.

Permissions

The first step I took was to define a set of three permissions for my new product type. To do that we use drupal’s hook_perm and simply return an array with the name of the permissions:

function licensable_perm() {
  return array('create licensable products', 'edit own licensable products', 'view licensable subproducts');
}

Now our module’s permissions will be available through the access control menu, and we can test for them with the user_access function. We use the hook_access callback to tell drupal when to apply our permissions:

function licensable_access($op, $node) {
  global $user;
 
  switch ($op) {
    case 'view':
      break;
    case 'create':
      return user_access('create licensable products');
      break;
    case 'update':
    case 'delete':
      return user_access('edit own licensable products') && ($user->uid == $node->uid);
      break;
  }
}

The Product API

Since this is a product we need to connect into the ecommerce module’s hook_productapi function. That works like most other drupal callbacks, sending in a reference to a node object, and the name of the operation to be performed. The key operations we’re interested in are:

wizard_select
Provides a list of product options provided by this module to be presented in the product creation wizard
subproduct_types
Provides a list of the types of sub products this product supports. In this case that allowed us to have a parent ‘licensable product’ which was the overall product, and then specific license types (single-user, 5-user, etc) as its children.
attributes
Products can have numerous attributes assigned to them. You can use this operation to do calculations about whether products are in stock, and related tasks.
cart add item
This is called whenever a user tries to add a product to the cart. Sub products need to intercept it to make sure the correct variation ends up in the cart, but we just let the standard subproducts module handle it.

As this is a license which can be generated on-demand our product is always in stock. And for most operations we simply pass the request up to the chain to the generic product module. Our function looked like:

function licensable_productapi(&$node, $op, $data = null, $a4 = null) {
  switch ($op) {
    case 'wizard_select':
      return array('licensable' => t('licensable product'));
      break;
    case 'subproduct_types':
      return array('licensable');
      break;
    case 'attributes':
      return array('in_stock');
      break;
    case 'cart add item':
      return subproducts_cart_set_subproduct_variation($node, $data);
      break;
    default:
      return module_invoke('generic', 'productapi', $node, $op, $data, $a4);
      break;
  }

A Final Touch

One other requirement we had was not to show the node pages for individual subproducts. Instead we’re showing a general product page and then a table of options. So as well as making sure the subproduct nodes weren’t directly linked to, we hooked into the node api to intercept requests for those nodes and redirect them to the parent product:

function licensable_nodeapi($node, $op, $arg) {
  // If the node has a pparent value it is a subproduct so we know we need
  // to redirect it.
  if ($op == 'view' && $node->ptype == 'licensable' &&
    $node->pparent && ! user_access('view licensable subproducts')) 
  {
    if ($_SERVER['REQUEST_URI'] == url('node/' . $node->nid)) {
      $url = preg_replace('!^/!', '', url('node/' . $node->pparent));
      drupal_goto($url);
    }
  }
}

Conclusion

Creating new product types in drupal is a very simple process, and very flexible with it. This is admittedly a straightforward example, but also serves to show just how simple it can be. In a follow up post I’ll show how we hooked in to actually generate the licenses and send them out.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

Scodigo Site Launches

14 February 2007 (8:05 am)

By James Stewart
Filed under: Announcements
Tagged: , , ,

Back in August I wrote about SmartPill PHP Edition. SmartPill PHP Edition is a plugin for the filemaker database that embeds the PHP engine, opening up a whole new world of flexibility and open source tools to Filemaker developers.

For the past couple of months I’ve been working with Samuel Bowles and Micah Woods (President/Founder of Scodigo) to launch the Scodigo website, promoting that plugin and their other services.

As befits a site promoting a PHP plugin, it’s PHP driven, using drupal for content management and ecommerce features, and a few custom modules that do things like generate licenses for SmartPill on the fly. If time allows, I may write up some notes on how we did that.

You can find the site at http://www.scodigo.com.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

XML_Feed_Parser stable

26 December 2006 (4:25 pm)

By James Stewart
Filed under: Announcements
Tagged: , , , ,

I’ve just released the first stable version of my XML_Feed_Parser library through PEAR. I’ve been working on the code for about 18 months now, it’s nearly a year since the first beta, and some time since I last had to make any significant changes, so it seemed like it was time to open it up to a wider audience.

You can get it through the usual channels, either downloading it directly or using the PEAR installer, and PEAR provides a bug tracker should you find any problems or have ideas for enhancements. My time to implement enhancements will be very limited, so I’m also very interested in hearing from anyone who’d like to sign on as a developer to help keep the package moving forwards.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

XML_Feed_Parser RC2

9 November 2006 (10:24 am)

By James Stewart
Filed under: Announcements
Tagged: , , , ,

I just rolled and released a second release candidate of XML_Feed_Parser. Mohanaraj Gopala Krishnan had pointed out to me that the parsing of atom text constructs wasn’t quite as flexible as the RFC allows for and was kind enough to supply an initial patch to improve support.

Since HTML_Safe isn’t stable yet my plan is to put clear security advice in the manual and then if there aren’t any new issues with this release candidate to release it as a stable version. Once HTML_Safe stabilises I’ll revise the manual, work in support for that and release a new version.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 
« Previous PageNext Page »