UPDATE: the DrupalService has been updated by the DrupalProxy, a much more powerful implementation. The 17th of november will see the release of a new Task for the DrupalProxy (DrupalInvokeTask) that will replace other Tasks for Drupal.
An example of how you can use custom tasks in sequences is demonstrated by the use of some Tasks in the DrupalService. This post will demonstrate how two very easy to create Task subclasses give you a general solution to handling a specific dataflow from Drupal. We will show you how you can abstract the repetitive flow of connecting to a drupal backend and getting a specific set of nodes from a certain view.
The normal flow of interacting with a drupal backend is by first connecting with the system to get a session id, this is advised as it gives better security handling. When you have the session id, you would want to retrieve data from the nodes in Drupal. After you have all the node data you want to manipulate it, for instance, generate a view where you can access all the nodes’ data.
The previous paragraph has “Sequence” written all over it, so we will use our very powerful Task based Seqence managing package to abstract away all the low level details of interacting with Drupal, to be able to quickly get our data without writing a lot of communication code.
//the sequence that will load our data from drupal private var sequence : Sequence; //a list that holds nodes private var nodes : List = new LinkedList(); public function main() : void { //a drupalService that needs a session for security. var service : DrupalService = new DrupalService("http://www.example.com/amfphp/gateway.php", true); sequence = new Sequence(); //because we need a session, we first must connect. create a task to connect before getting any node data sequence.add(new DrupalConnectTask(service)); //now get some node data! in this case nodes with id 1 to 100 and use the myNodeHandler method to handle the incoming node data. for(var i : int = 1;i < = 100; ++i) { sequence.add(new DrupalNodeTask(service, i, myNodeHandler)); } //add callback task to sequence of tasks to process all the nodes sequence.add(new CallBackTask(allNodesLoaded)); //start the sequence. sequence.execute(); } /** * callback method specified in the DrupalNodeTask constructor. * It takes a DrupalNode object as it's first argument. * The node is passed in via the DrupalNodeTask */ public function myNodeHandler(node : Object) : void { //we handle the node here, in this case, we just put it in a list for later manipulation nodes.add(node); } /** * the last task in the sequence is a CallBackTask which just calls this method. * We will handle the end of the sequence here and manipulate the nodes we have retrieved from the backend. */ public function allNodesLoaded() : void { //we can now manipulate all the nodes in the "nodes" LinkedList. //for example, put all the data in Domain Objects and generate a view from it, //like a list where you can click on the title to get the node data etc. }
The previous code has shown how simple it now is to get data from drupal and manipulate it and how we totally abstracted away all low level drupal connecting code. You can check out the DrupalNodeTask and DrupalConnectTask to see how simple it is to set up a Task specific for your wishes.
There also is a DrupalViewTask that works exactly the same as the DrupalNodeTask, except that it takes a view name as an argument instead of a nodeId and the callback method will handle the data which came back from the view request which is a multidimensional array with possible multiple nodeId’s or node data. For more information on this, you can also read the comments in the earlier DrupalService post where there is a question about this.
It is not only easy to implement, but also easy to read as code. All the tasks are manipulated in separate Callback tasks…Nice, because I don’t wanna use events. Greate job
Here’s my first attempt to convert my Drupal portfolio into flex :
http://www.brandnewside.com
Sorry, the content is in French, translation to English is on the way. But amateurish developer like me can still look at the source : comments are in English… well, sort of…
Professional developer : you’ve been warned.
Anyway, thank you again, your stuff works perfectly.
Hi Benoit,
veryyy nice.. Also very nice to see that you actually used the package as envisioned by us (thanks to letting everyone be able to view your source code) and in the way we use it ourselves. Subclassing the Task class to create powerfull sequences etc. Nice to hear you could really use it and thanks for letting us know
take care
Hi,
very interesting stuff.. but I don’t get one thing. In the code above you create one service:DrupalService and pass it as a parameter to DrupalConnectTask. When DrupalConnectTask finishes, DrupalConnectTask.destroyTaskHook is called where you destroy dataService that was passed in (by calling this.ds.destroy()) . This is from DrupalProxy destory() method description:
/**
* cleans up the class.
* destroys all references, frees memory etc.
* after a call to destroy, the instance of DrupalProxy cannot be used anymore
*/
(notice the last line - this instance of dataProxy cannot be used anymore).
So DrupalConnect task is done and sequence continues with next task : which is first of the 100 DrupalNodeTasks. Which is passed in same drupalProxy resource (that should be already destroyed right now).. This task does its job, again destroys drupalProxy, next task kicks in, with same drupalProxy, and again and again :).
Am I missing somethig here?
Is DrupalProxy a unkillable vampire or what?
Sorry, maybe it’s too late for me , but I just can’t figure this one out. Will be glad for any explanation. And yes, I’m a programmer, not a newbie, so don’t go soft on me :).
Happy Halloween everyone.
Arrgh :).
Now I see something. After rereading my post. DrupalService and DrupalProxy. I got them mixed up.
So I assume drupalService (outdated now, i suppose) wasn’t so brutal in it’s destroy method, and was reusable after one task?
What’s your approach now when using DrupalProxy and sequencing? Because DrupalConnectTask and DrupalNodeTask still destroys the resource, so is there some other way to create such sequence with only one drupalService, or you have to create drupalService for each task? Or is there still something else I don’t see… ?
Hey SP,
the resource itself is not destroyed, only the local reference to the resource in the specific task. It’s a memory cleanup thing. The DrupalProxy reference is nulled, so the Task does not point to it anymore. The drupalProxy instance itself is not touched at all.
We’re about to release (17th of november) the DrupalInvokeTask which will make all other tasks obsolete and will allow you to sequence all of your drupal calls with the help of only this task.
a little example with some demo code for the adobe user group xl event (www.adobeusergroupxl.nl):
sequence.add(new DrupalInvokeTask(drupal, “system”, “connect”)); sequence.add(new CallBackTask(drupal.setRemoteCallId, “data”));
sequence.add(new DrupalInvokeTask(drupal, “node”, “get”, 66));
// add a pause for the demo!
sequence.add(new CallBackTask(sequence.pause));
/*
* tag the next call to node.get with an id of “picture”. We are calling node.get again but with a different purpose.
* the handler for all node.get calls is the same however.
* the remote call id allows us to distinguish between multiple calls to the same method (we could also distinguish on the node id: nid)
*/
sequence.add(new CallBackTask(drupal.setRemoteCallId, “picture”));
// node 122 is predefined and is a cck made node in drupal that has an extra field with a url of a picture in it.
sequence.add(new DrupalInvokeTask(drupal, “node”, “get”, 122, new Array(”nid”, “type”, “field_picture”)));
sequence.add(new CallBackTask(sequence.pause));
// it is often not needed to tag the call, but it is easy for debugging
sequence.add(new CallBackTask(drupal.setRemoteCallId, “sleep 3″));
sequence.add(new CallBackTask(write, “sleep for 3 seconds (timout test)”));
take care