One thing that's really nice about working on your own Drupal projects is that you get to share what you're working on (no NDAs, woot!). This particular project (Build a Module.com) is a video tutorial site for newer Drupal developers. For a while, I had a single product offering, but feedback made me realize that people like options. So, I decided to to offer single video purchases as well as 'collections,' or groups of videos bundled up into a single product. I also needed to make sure that customers had the right permissions set on files depending on their purchases.
Here's a video outlining the solution I came up with. Scroll down below the video for further details.
About the flow
I have 3 node types:
- Videos - Contains description and video file in a file field
- Single Video Product - Is an Ubercart product with a node reference CCK field pointing to a single video
- Collection Product - Another Ubercart product, but this one has a node reference CCK field that points to a number of videos
I didn't realize that a node reference field could point to multiple nodes before a fellow Drupalista pointed it out to me. Eesh! I really could have used that info a year ago.
So here's the flow:
- A user adds a Single Video Product or a collection to their cart
- They check out and complete the purchase
- They visit a video page
- A custom function checks against their orders to see if they have access to the video. If they do, they're in.
The function used in step 4 uses several queries to determine access. The queries check for the following:
- Is the product free? If so, show the video.
- Has the user purchased a product that includes the video file that this Single Video Product type points to?
- Same check for a Collection Product type
- If there is no product for the video, then give access (some videos, like the intro video, don't have an associated product)
In the hook_file_download, the same function is called, but I first have to figure out what node the file belongs to. In Drupal 6, hook_file_download only supplies you with the name of the file. No node associations or anything, so you have to connect the dots with your own query. I think the reasoning is that a file can belong to multiple nodes, but since my workflow doesn't allow that, it's not an issue.
There are some good things about this approach, such as when files change in the nodes (i.e. you upload a video with corrections), even though there is a new file name, the node association will remain the same and access will be granted.
For a while I was using a module called File Access, which allows you to set granular permissions for each file based on user or role, but because I would have to build a connector action between a purchase and the access, and then respond when new files are uploaded, I figured I would keep it simpler and just cross-reference the orders instead. The downside is that if my products change, so will access. Also, using File Access would enable access based on field, rather than on node. So, if I have two different versions of a file on the node (iPod version and full-size) and wanted to sell them separately, I would need something more complex.
Part of the reason I'm putting this info out there is to get feedback and see if a module that handles this type of access and setup would be a welcome addition to Drupal contrib, so feel free to drop me some feedback below.