22 June 2009
This article assumes that you have a working knowledge of ActionScript 3, and that you know how to use FTP for sending files to a web server. You may want to start by reading Chris Charlton's article, Building a Drupal site in 10 steps, which provides more in-depth information about installing and setting up Drupal in general. It would also be beneficial to look at the SWFAddress site because I discuss using SWFAddress toward the end of the article.
Intermediate
This article takes you through the process of using Adobe Flash or Adobe Flex to build a site with Drupal, an extremely popular open-source content management system (CMS) written in PHP. Along the way you'll get a better understanding of the benefits of this technique, also known as "Druplash" or "Druplex."
I designed this article so that you can stop reading at any time and start using Drupal with Flash. However, the further you read, the more advanced the topics and the more full-featured the setup.
Many successful sites created with Adobe Flash use XML files, or no external files at all, for their content. Here's my list of reasons why you may want to consider combining the Flash platform with Drupal:
The process of using Adobe Flash with Drupal is pretty simple; in fact there are really only four steps to follow:
The first step is to install the Drupal CMS onto a PHP-enabled server. I strongly recommend using your local machine for testing if possible. It's true there's quite a bit of groundwork needed to get this set up, but after the first time it can be done really quickly—and it pays you back many times over once you're up and running.
For more detailed information on installation, visit the Drupal 6 section of the Drupal online documentation.
This article assumes you are installing to the web root folder. You can install to any location, however, such as a subfolder or a subdomain without modification. Here are the basic steps to installing Drupal on a PHP-enabled server:
Note: Make sure you extract the Drupal ZIP file into the folder directly because you may miss the invisible .htaccess file if you just use Windows Explorer or the Mac OS X Finder to drag the files. Alternatively enable "show hidden" files on your system to copy this file manually.
To do this on a Mac/Linux/Unix machine, open a command prompt, change to the sites folder, and type chmod a+w default. In Windows you can set the file permissions for the "Internet Guest Account" via the File Properties dialog box. Alternatively, if you are using FTP to access files on a remote server, you can usually add the write permissions using your FTP client. The Drupal site has detailed instructions on how to do this for most systems.
When installing Drupal, you may have noticed an option for enabling "clean URLs." If not, don't panic, you can enable this via the Drupal administration screens later on. Either way, this option deserves some explanation.
When you access a page (or node) in Drupal in a web browser, the URL is in a format like http://mysite.com/?q=123, which is quite nondescriptive. Clean URLs do not contain query string variables; instead, they just contain an easy-to-read path made up of words and slashes only—for example, http://mysite.com/node/123. When clean URLs are enabled, the server needs to dynamically rewrite them into the query-string format that PHP understands. This makes the URLs much more descriptive to both users and search engines alike but still allows the underlying PHP engine to interpret the request correctly.
Follow the instructions on the Clean URLs page in Drupal via Administer > Site Configuration > Clean URLs. In most cases you just need to enable/install the mod_rewrite Apache module on your server if it is not already switched on, and/or allow .htaccess files to set the rules for your site's folder.
You'll be using the Path and Pathauto modules to allow you to specify custom paths, or aliases for your nodes. In this context, a path is the portion of the URL that appears after the slash that immediately follows the domain name. The paths in Drupal will match directly with the (SWFAddress) paths in ActionScript, giving you a one-to-one mapping between human-readable paths and the node IDs that uniquely identify the content. This is why the clean URLs option must be enabled if you want deep-linking in your site. (There are ways to work around this if you absolutely cannot enable clean URLs.)
To use Drupal with content that you create in Adobe Flash or Adobe Flex Builder, you'll need to add a few very useful modules. Just extract the files found in the ZIP file into your sites/all/modules folder to create a new folder for each module. Install the following modules:
Note: The official 6.x-0.14 release has a bug that prevents us from generating a sitemap, so please download the 6.x-2.x-dev development snapshot instead (unless the official release is newer than 6.x-0.14 when you read this note, of course).
After installing the modules, you need to activate (or enable) them. I recommend turning them on one or two at a time. Drupal can choke if you check all of them at once because the first time you enable a module it runs an installer script for it.
Enable the following modules using the Administer > Site Building > Modules page. I've included any included submodules that you'll also need to enable:
There are several other modules that you can enable to add more power to your website. For example, when you specify images in your nodes, the Imce CCK Image module allows the user to upload and pick files in one step, rather than pasting the known file-path of an already uploaded image file. However, I do not recommend using these additional modules until you are already comfortable with how everything is working, because they can take a lot of time to play with and tweak to get just right:
After you enable all the relevant modules, you need to enable anonymous access to the Services module so that you can call its methods from your application. To do this, visit the Administer > User Management > Permissions page (see Figure 1) and click the anonymous and authenticated access check boxes for the following:
Finally, save your changes when done.
Note: You can use this Permissions screen to enable all sorts of rights for anonymous and authenticated (logged-in) users, as well as other types of roles you create, such as moderators or content creators. As the administrator, you always have access to all features.
You need some content for Flash Player to be able to display anything. Specifically, you need a node—Drupal's term for a page, blog post, or any other content that you might create for your site. Later in this tutorial you'll be creating custom "content types," more advanced versions of the simple Page and Story types that come standard with Drupal. For now, you can start by creating a Page with some text so you'll have something to look at.
Note: A great way to generate age-old placeholder text ("Lorem ipsum dolor sit amet, consectetur adipiscing elit") is the Lorem Ipsum generator.
Create a test page by going to Administer > Create Content > Page in your Drupal site. This node will have node id "1" (you can click Edit and check the URL to verify this but it's not important). A Page has a title and a body field by default. The body can be HTML, and you can configure Drupal to allow all or just some HTML tags (it will strip any disallowed tags when you save).
You may be thinking, HTML isn't much use to Flash Player unless perhaps you're writing XHTML that you want to parse as XML. Even that is quite limiting because it requires the person entering the content to type XML manually and know exactly what to write.
Later on I'll cover adding extra fields to Nodes so that your pages contain videos, arrays of buttons, and information that will enable your SWF application to identify these fields individually by name. But for now, you just need to see how to access the contents of a Drupal node from within a SWF application.
If you visit the Administer > Content Management > Content page, you'll notice that this new page is now listed; you can always come back here to edit or remove it.
You have a Page in the site, but right now it's only accessible as HTML in the web browser, so how do you get at this data in ActionScript?
The first step is to visit the Administer > Site Building > Services page and uncheck the Use Key and Use Session ID options. This allows you to access the services from the comfort of Flash without putting the SWF file on the server.
Next, create a new Flash FLA (or Flex Builder project) and add the Flash Drupal library to the ActionScript 3 class path via the project settings panel. You now need to make a request of the Drupal Services module, so if you are using Flash, open up the Actions panel, select frame 1 on the Timeline, and enter the ActionScript code below. If you are using Flex Builder, enter this in a suitable place in your class:
import uk.co.richardleggett.drupal.services.NodeService;
import uk.co.richardleggett.drupal.model.Node;
import uk.co.richardleggett.net.services.events.*;
var nodeService:NodeService = new
NodeService("http://localhost/services/amfphp");
nodeService.addEventListener(ServiceResultEvent.RESULT,
nodeServiceResultHandler);
nodeService.addEventListener(ServiceFaultEvent.FAULT,
nodeServiceFaultHandler);
nodeService.loadNodeData("1", Node);
function nodeServiceResultHandler(event:ServiceResultEvent):void
{
trace("result: " + (event.result as Node));
}
function nodeServiceFaultHandler(event:ServiceFaultEvent):void {
trace("fault occurred: " + event.message);
}
Note: The URL in the NodeService constructor should point to your Drupal installation.
Test the SWF file. You should see the contents of the Page along with a few other properties in the output panel. If you like, dig into the Node class file to see what you get as standard.
Take a close look at what this code does. First of all, it imports the classes I'm going to use and creates a new NodeService instance, passing it the AMFPHP gateway location in the constructor (you can get your AMFPHP gateway address from the Services page in Drupal; here I installed Drupal in localhost, the root of my machine). The code also has two event handlers, one for a result and one for a failure. Then it calls loadNodeData(), passing it the node ID ("1" in my case), and the class to use to parse the result (the basic Node class here). Finally the two handlers for the result and failure simply output the outcome; in the case of a result, the result object is a Node.
I think you'll agree that requesting one node at a time like this would be cumbersome for a site, and hard-coding the nodes' IDs is really bad practice. Fear not. I'll be using the Views module in Drupal to get a sitemap that lists all the nodes in the site—giving me their IDs, so I can load the data—and their paths (the portion of the URL after the domain; for example, "about-us" or "products/cars") so I don't have to hard-code IDs.
Note: For debugging, you can use Charles or Service Capture to view the AMF request and response objects as they are sent and received.
If you see NetConnection.Call.Failed in the Output panel, make sure you've enabled anonymous access to the Services module, as outlined in the "Setting permissions" section of this article, and that you can visit your AMFPHP gateway in the browser without error.
If you see NetConnection.Call.BadVersion in the Output panel, it could be a PHP error. Check your PHP/server error logs (turn on log_errors and set the error_log file in php.ini if it isn't already enabled). On Mac OS X you can view your PHP error log using the built-in Console application; it appears as /var/log/apache2/error_log in the list.
It was quite simple to load a node's data by using NodeService along with a known ID. But the SWF application shouldn't need to know these Node IDs because it limits the person using the CMS, and it is not easy to add new nodes without updating the application.
You can introduce a sitemap to solve this problem. Think of this as a list of all the nodes in the site (I'll cover filtering later). In this list you get just a few details about the node: its title, ID (nid), type, and path. In addition, by default SitemapService gets a few other properties, including language, parent, and order_by, among others.
With this information you can display site menus, look up a node by path, and so on. For example:
sitemap.getNodeByPath("about-us");
You can also view the hierarchy, which will be discussed later in the "Node hierarchy (parenting nodes)" section:
trace( sitemap.getNodeByPath("about-us").childNodes );
In effect, you have access to the structure of a Drupal site and all of the content within it. One of the first things I do in an application is load the sitemap and store it so that I can use it throughout the site to figure out what data to load, and even what to display (by inspecting the Node.type property).
There's only one problem: Where do you get this magical sitemap? The answer is you need to set up a sitemap View in Drupal using the Views module. A View in Drupal is like a database query. You can choose what nodes to pull out and list based on certain criteria. Views can be used to grab all kinds of information out of a Drupal site—anything from the sitemap to a list of products for an online shop.
Create this View by going to Administer > Site Building > Views > Add. Type sitemap for the name, Sitemap for the description, and leave Node as the view type; then click Next.
The key thing to note on the following screen is that while you can preview your view, you need to click Save to apply any changes. This may sound obvious, but with the way the UI works, you can sometimes be testing your application and wondering why it isn't updating. It's easy to forget to save.
Finally change the Row Style to Node in the Basic Settings and change the Items To Display to 0. That way it won't limit how many results you can see. Click Preview to see whether there is a node in the results. Make sure to click Save (this screen doesn't make it too obvious) and then use the Administer > Site building > Services screen to test this out.
Simply click views.getView and type sitemap as the View Name, followed by nid,type,path,title,parent as the Fields. You should then see a dump of the objects returned when you click Call Method. If you don't see views.getView on the Services screen (see Figure 2), enable the Views Service module from the Administer > Site building > Modules screen.
Now you're ready for a practical example of loading the sitemap from ActionScript. Create another project and enter the following code:
import uk.co.richardleggett.drupal.services.SitemapService;
import uk.co.richardleggett.drupal.model.*;
import uk.co.richardleggett.net.services.events.*;
var sitemapService:SitemapService= new
SitemapService("http://localhost/services/amfphp");
sitemapService.addEventListener(ServiceResultEvent.RESULT,
sitemapServiceResultHandler);
sitemapService.addEventListener(ServiceFaultEvent.FAULT,
sitemapServiceFaultHandler);
sitemapService.loadSitemap();
function sitemapServiceResultHandler(event:ServiceResultEvent):void {
trace( (event.result as Sitemap).nodes );
}
function sitemapServiceFaultHandler(event:ServiceFaultEvent):void
{
trace("a fault occurred: " + event.message);
}
With any luck you'll see an array of nodes in the output panel (each will display the basic Node fields). You now have full access to all the nodes in the site, new or old, and you can use methods such as sitemap.getNodeById() or sitemap.getNodeByPath() to pull out specific nodes. If you've been using the Node Hierarchy module in Drupal, the childNodes arrays should also have been populated. I talk more about that in the "Node hierarchy (parenting nodes)" section.
Either way, you can inspect the node.type property in the sitemap to determine what type of node you have, and you can attach or load the appropriate content to render that node in Flash Player (most likely giving the Node object itself as the data provider to your view).
The SWFAddress Drupal module passes in the Drupal path that the user initially requests into the Flash SWF as a FlashVar with a value like "about-us" or "products/someproduct". You can use that FlashVar to request the node's content (by using the sitemap to map the path to a Node ID). Using the SWFAddress library is also a great way to handle navigation within your site because it updates the browser's address bar and allows people to copy and paste links in e-mail messages or IM. It also supports browser bookmarking.
Note: For more information, view the presentation by Lee Brimelow to see a demo of using the SWFAddress library to enable direct and deep linking of a SWF file.
Those of you who are experienced in building data-driven websites in Flash may be thinking that my approach so far has been incredibly basic and inflexible. But this is actually where it gets interesting. The next few sections describe how to expand the technique to support more complex types of content in the CMS.
Now that you have the ability to populate a site with nodes and load them in ActionScript, the next logical step is to figure out a way of storing the information in a more SWF-friendly format. At the moment the two fields you can use to store information is the title and the body, but the body is just a chunk of HTML. Custom content types (enabled by the CCK module) allow you to define new Page types that can contain any fields you wish. For example, I could have an AboutUsPage content type with the following fields:
In Drupal your custom fields are prefixed with field_ automatically, so these extra fields would appear in the AMF result object as field_partner_link and field_image, respectively.
To create this AboutUsPage content type, navigate to the Administer > Content Management > Content Types screen and click Add Content Type. For the Name, type something readable by humans such as About Us Page (see Figure 3). For the Type, use a string that you can reference in code, for example aboutUsPage (remember that Node includes the type property when you retrieve one from the sitemap or via NodeService). I recommend disabling comments in the Comment Settings. If you intend to have pages under this one, be sure to select the Can Be Parent. Click Save when you are done.
Back on the Content Types screen, click Add Fields. Follow the wizard, typing partner_link as the Field Name and Partner Link as the Name. Select Text as the Field Type and click Continue. Select Textfield for the Widget Type. On the settings screen for this field type, select Unlimited for the Number Of Values. When you create a new AboutUsPage, this field will have a button to add multiple entries, and in ActionScript you'll get an array of field_partner_link values. Follow the same steps for field_image.
Now it's time to create a node using the AboutUsPage content type. On the Create Content screen, create a new AboutUsPage, filling in a few values for the newly added fields. When you get to URL Path Settings, you'll see that Automatic Alias is already selected. I'll explain what this means shortly, but for now deselect it and type about-us for the path. This means when you save your content it will be accessible at http://localhost/about-us (with localhost being whatever server and path you are using).
Note: When you go back and edit content, Drupal has the habit of re-enabling the Automatic Alias option, which will change what you see if the automatic alias is set up to use a different value. Be sure to deselect it if you aren't sure that the automatic alias settings are set up for this content type. Also, I recommend you apply the patch that is available to help fix this. It adds a new "Update Setting" option in your Pathauto settings page to make sure it doesn't automatically generate a new alias for content that already has one, but you must choose this option for it to take effect. (See the Drupal documentation for help on applying patches.)
By default, all content/nodes you create will have a path of "/node/X" where X is the node's ID. (If you do not have the clean URL option enabled, it will be "/?q=X".) You can always visit /node/X to view a node, but it's more useful to use a human-friendly alias instead, so "/node/5" might become "/about-us".
The Path module enables the textfield you saw when creating your content. It allowed you to enter "about-us", and it will display that node to the user without displaying "/node/X" in the URL. See the Path and Pathauto pages in the Drupal online documentation for more information.
Recall that you deselected the Automatic Alias option when creating the AboutUsPage node. The Pathauto module allows you to set up rules for each content type that dictates what path should be given automatically to any content/nodes created. In this case I had you disable the functionality because you haven't yet set up the automatic alias pattern for the AboutUsPage content type. An automatic alias is just a path that is named based on the content type you are creating, and it can also include the node id, or other information about the node you are creating. On the Administer > Site Building > URL Aliases page you'll see an alias named "about-us", which you gave for the AboutUsPage when you created it.
If you click Automated Alias Settings you can choose to specify the default path names for all known content types. For example, if you type about-us for the Pattern For All AboutUsPage paths, then from now on if you create another About Us page, the path will be given as "about-us". Of course this would cause a problem if you had two About Us pages because they'd have the same path, but Pathauto lets you use replacement patterns. For example you could use "about-us/[nid]" where "[nid]" is replaced with the unique node ID, for instance "about-us/2". This solves the problem of having many pages that use the same content type.
Note: One common problem is that once a piece of content has been assigned an alias, as it has already in this case, you must delete that alias from the URL Alias > List screen, go back to the Automated Alias screen, select the Bulk Generate Aliases For Nodes That Are Not Aliased option, and click Save Configuration to regenerate the aliases for any content that doesn't have one. In practice, you shouldn't encounter this problem if you make sure you set up the automatic alias pattern for a content type before you create any content using it (or simply don't use automatic aliases at all, for example on sites where new content is rarely added).
Having a flat sitemap doesn't make for a natural site structure. Sure, you could fake it in ActionScript, or you could just rely on your paths to reflect a hierarchy, but that's the long route.
The easy route is to use the Site Hierarchy module in Drupal. After enabling this module, you can edit any existing content via Administer > Content Management > Content, scroll down to Node Hierarchy, and select a parent. If you don't see this option, make sure you have enabled the Can Be Child option in the Content Type for the content you are editing, and the Can Be Parent option for the one you want to be the parent (use the Administer > Content Management > Content Types page).
Note: I usually create a Home node in Drupal, promote it to the front page, and set it as the parent of my top-level Section pages so that I can easy build a menu in ActionScript from the Home node's children.
If you now run the Sitemap application that you created earlier, you'll see that the child node now has a parentNodeId value. The SitemapService class automatically builds the hierarchy if this is found, so someNode.parent will give you the parent Node object and parentNode.childNodes will give you the array of child Node objects. See the Node Hierarchy page in the Drupal online documentation for details.
Being able to add fields to a content type and even having the ability to set them to "multiple" (so that you can allow more than one entry, producing an array) is great, but it soon breaks down when you want to represent a complex or compound object. This is something I do all the time in ActionScript by writing classes or value objects—for example, a Button—which might be defined as having a label and a link (or path).
Consider a case in which you want to display three buttons on your home page. One way to do this is to create a HomePage content type in Drupal and add two multiplevalue text fields for it: field_buttonlabel and field_buttonlinkpath.
What you'd get back in ActionScript is two separate arrays of values that you can loop through in order to build one array of single Button objects. This is an unnatural way of working; it quickly gets confusing to someone editing the node in the CMS and you end up with lots of fields.
The solution is to use the Flexifield module. This gives you a new field type to choose from—namely "flexifield". Unlike other types, Flexifield allows you to have multiple input fields for a single field without writing any PHP (the normal route is to write custom field types using CCK). It does this by allowing you to choose a content type to act as the template for your field type. See the Flexifield page in the Drupal online documentation for details.
Remember that up until now you have only used content types to act as the template for an entire node/page. Go to Administer > Content Types and create a new content type named FieldType_Button. Add two fields to it: field_label and field_path (try to name your field types so that they can be reused in many situations). Both fields should be set to textfield, single line, single entry (both are default).
Note: You'll notice I prefixed my new content type with FieldType_. I do this to make it clear that this content type is not to be used to create nodes/content; it's specifically for the Flexifield used in other content types.
With the new content type defined, go back into your HomePage content type (Administer > Content Types > AboutUsPage > Edit) and add a new Flexifield that uses FieldType_Link. Name it field_link and set it to Multiple to allow multiple links in a page. Now create a new Links Page via Create Content > AboutUsPage. You'll see that you now have a Link field which contains within it two fields: field_title and field_path. You can enter as many Link fields as you like because we set the field_link field to allow multiple entries.
In ActionScript you get back a single array called field_link, and each entry in this array contains two values, one for field_path and one for field_title. So to access the third link's title you may use trace(node.data.field_link[2].field_title).
I hope this article provided you with some insights into how to use Adobe Flash and Flex Builder with Drupal. In practice, I would expect you to integrate this raw technique into the site-building framework you already use, such as PureMVC, Gaia, Mate, and so on. (Jeremy Wischusen summarizes the most popular frameworks currently available in his article, Choosing a Flex framework.) This way you can automate many of the tasks involved with getting content from the CMS when the user navigates around your site, enabling you to interact with Drupal at a higher level.
I haven't touched on how Drupal displays the nodes that you are reading into ActionScript when it encounters a search engine or device that does not have Flash Player installed (essentially, where SWFObject fails to embed the content that is played back in Flash Player).
There are several options here that range from simply outputting the node's fields one after another as HTML (this is what Drupal does by default), to hiding certain fields via the Content Type settings (for example hiding all the Flash Player-only fields and just displaying a "body" and "title" field), to writing PHP or CSS that reads the custom fields and outputs them nicely in HTML. Read Chris Carlton's article, Using Drupal themes with Dreamweaver CS4, to get started.
As for Drupal itself, version 7 is currently in development and looks to be very promising for rich media. In particular there's a lot going into making the CCK module part of the core, which could mean that fields become first-class objects. That opens up the possibility of having Flex-based editors for content types inside Drupal itself, and most likely not needing Flexifields that use content types for their structure.
Either way, the future looks great for Drupal-backed sites built with the Adobe Flash platform.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License
| 04/23/2012 | Auto-Save and Auto-Recovery |
|---|---|
| 04/23/2012 | Open hyperlinks in new window/tab/pop-up ? |
| 04/21/2012 | PNG transparencies glitched |
| 04/01/2010 | Workaround for JSFL shape selection bug? |
| 02/13/2012 | Randomize an array |
|---|---|
| 02/11/2012 | How to create a Facebook fan page with Flash |
| 02/08/2012 | Digital Clock |
| 01/18/2012 | Recording webcam video & audio in a flv file on local drive |