There are several ways of accessing the RedDot CMS API. You can use RenderTags or use the RedDot Query Language, also known as “RQL”. This article explains how to use RQL for advanced requirements like event controlled RQL, remote RQL execution, binding RQL to workflows and much more.
Have you already seen this article RQL in a nutshell of the brilliant Manuel Schnitger? Yes? Well, at some point you’ll have questions which are not answered in the formerly mentioned article.
Therefore Manuel is back with this new article full of useful goodness that will help you when creating RQL-based applications.
Usually an RQL plugin is called via a link in SmartEdit or SmartTree and will be executed in the second you click on the link…..so user interaction is required. But what has to be done if you want the plugin/application to be executed when a specific event (e.g.: page released) in the workflow is reached? Let’s do it step-by-step.
In this sample the goal is that you trigger an RQL application via the workflow. The action that is performed is not important….just the steps that result into performing the action.
Step #1: Creating a user defined job in the Server Manager
a) Go to the Server Manager > User defined jobs and click on "Create user defined job" in the action menu
Figure 1:Server Manager – Administer user defined jobs
b) in the upcoming dialogue enter a name for this job (e.g.: myNewJob)
Figure #2: Add a name for the job
c) in the next dialogue activate the checkbox "call event controlled" and deactivate the other one (important!)
Figure 3: Activating the option “Event controlled”
d) in the next dialogue choose the option "Open URL" and enter the url to your RQL application
Figure 4: Adding the URL of your application
Step #2: Assigning the user defined job in the project
a) Enter the SmartTree
b) create a workflow
c) click on "Page released" and then on "add reaction" (of course jobs can also be triggered when the workflow level is different to "page released" )
Figure 5: Small sample workflow
c) In the opening dialogue click on "Start job" and choose the user defined job you just created in the Server Manager.
Figure 6: Workflow triggers a user defined job (RQL application)
Ready and good to go!!! Now the RQL application will be triggerred each time a page that is connected to this specific list is being released.
Usually when you wish to start a job – when a specific step in the workflow is reached you also want to let the RQL application do something with the page in workflow. But then there is this:
And how can you transfer the GUID of the page into your application? It’s very simple: Just add another reaction to the workflow!
Click on the action "page released" then on "add reation" in the action menu and choose the reaction "Write workflow XML".
You will be asked for a location (folder) where the workflow xml file(s) shall be placed (see figure below) after closing the dialogue every time a page is released two things happen. First the workflow xml file will be written (one file for each page & event) under the specified path and after that the RQL application is triggered.
What you have to do next in your application is: Reading out the page guid and using it in your application.
Figure 7: Path for the workflow xml files
Sample code how to extract the GUID of a page and the GUID of the project the page is part of
Set oXml = Server.CreateObject("Microsoft.XMLDOM") Set rootNode = oXml.documentElement if rootNode.hasChildNodes() Then for Each e in rootNode.childNodes if e.nodename = "PAGEGUID" then sPageGuid = e.childNodes(0).text response.write "<br>PageGuid: " & sPageGuid & "<br>" end if if e.nodename = "PROJECTGUID" then sProjectGuid = e.childNodes(0).text response.write "<br>ProjectGuid: " & sProjectGuid & "<br>" end if next end if
Please be aware of the fact that -if you call an RQL application this way- you don’t have any session variables such as login guid or the session key. So you’ll have to write some RQL code for the login procedure and the validation (= connecting to a project). (If you should face issues with these steps… give us some feedback.)
EmptyBuffer – How to delete text element content using RQL
If you want to delete something using RQL you write something like <PAGE action="delete"
or <USER action="delete" or something similar depending on the thing you wish to delete.
This works well whenever you want to delete the "object" itself; it does not work when you’d like to delete the content (Text) of an object (Textelement). In order to delete a text from a text element or from a standardfield you have to save the so called "Empty buffer". (Of course the empty buffer can delete much more than just the content of a text element or standardfield.)
Sample for deleting the text of a text element:
sValue = session("EmptyBuffer") "<IODATA format=""1"" loginguid=""" & sLoginGUID & """ sessionkey=""" & sSessionKey & """>"&_ "<ELT reddotcacheguid="""" action=""save"" guid=""" & sEltGuid & """ pageid="""" id="""" index="""" type=""" & sType & """>" & sValue & "</ELT>"&_ "</IODATA>"
Q: What is the empty buffer?
A: It’s just a hash tag followed by the session key of the current user.
So this: response.write session("emptybuffer") and this: response.write "#" & session(sessionkey) result in the same output.
Generally plugins or other RQL based applications are placed on the editorial server meaning the server where the Open Text Management Server software is installed. And normally plugins are called via a link or RQL applications are triggered by the workflow. But what if you have a server where a specific application runs and when you want to execute RQL statements triggered by this application?
Example: There is an application that writes product related information into an XML file and you want to create a page on the editorial server based on this information.
What you could do is a) writing a small directory listener that notices when a new file is being written b) read out the relevant data and c) use the RQL bridge to communicate with the editorial server.
Ok, let’s do it step-by-step:
Step #1: Create a file called "RqlBridge.asp"
using this code and place it in a folder called "remoterql" under the plugins directory (obviously you have to create this folder ;-) on the editorial server.
<%@ Language=VBScript %> <%server.ScriptTimeout = 5 %> <% function sendXML(XMLString) set objData = server.CreateObject("RDCMSASP.RdPageData") objData.XmlServerClassName="RDCMSServer.XmlServer" sendXML = objData.ServerExecuteXml(XMLString, sErrors)end function XMLString = request("sXmlData") if XMLString <> "" then sReturn = sendXML(XMLString) Response.Write sReturn end if %>
As we can see, the function sendXML just executes the RQL statement. The function itself is called in the second block of the code. In the code below we then can see how the communication between the editorial server and the "other" server is managed.
Step #2: Create a file based on this code and place it on the "other" server.
As I’ve added some comments in the code to make it more clear what exactly happens.
First I just get the Login Guid. You’ll now ask: "How the hell did he get the login guid…? This file is supposed to be on the "other" server where no session variables are available…!" Right, I tested the RqlBridge on just ONE server (my editorial server), but the functionality also works when there are two servers.
sLoginGUID = Session("LoginGUID") 'Then the RQL statement is written in the variable "xmlString". xmlString = "<IODATA loginguid=""" & sLoginGUID & """>"&_ "<ADMINISTRATION>"&_ "<PROJECTS action=""list""/>"&_ "</ADMINISTRATION>"&_ "</IODATA>" 'Here we call the file "RqlBridge.asp" (on our editorial server) 'and transfer the RQL statement (xmlString) as the content of 'the parameter sXmlData. 'As written above the RqlBridge is just being used to execute the RQL. 'So as a result of this call we receive the server response from the editorial server. RqlRequest = GetServerAnswer("http://localhost/cms/plugins/remoterql/rqlbridge.asp?sXmlData=" & xmlString) Response.Write "<br/>Server Response:" & server.htmlencode(RqlRequest) & "<br/>" ' The function GetServerAnswer just calls an URL and returns the response. ' This is not related to the Management Server but is more a general functionality. Function GetServerAnswer(sUrl) Dim objHTTP, sServerAnswer Set objHTTP = Server.CreateObject("WinHttp.WinHttpRequest.5.1") objHTTP.SetTimeouts 0, 3000, 2000, 5000 objHTTP.open "GET", sUrl, false objHTTP.send if err.Number<>0 then sServerAnswer=err.Number err.Clear end if on error goto 0 GetServerAnswer=sServerAnswer end function
Ready! We are now able to create calls on server A that will be executed on server B. I don’t know if this is helpful for much people but at least I wanted to point out this option.
The next thing you might try and read out is the creation date of a page or perhaps the appearance schedule for a page. You will notice that the dates are not really readable as they are just floating point number.
So if you would like to display a date in a way that people can read it, you have to encode the date. And if you would like to save a date…. of course you have to decode it previously ;-)
The code below demonstrates both directions. If you create a plugin based on this code you will see how a serial date will be converted into a floating point number and vice versa.
<% 'converts a serial date into a floating point number that can be stored into the database mydate = "11/11/2010" set RQLObject = Server.CreateObject("RDCMSAsp.RdPageData") mydate = RqlObject.EncodeDate(myDate) response.write mydate & "<br>" mydate = "30493" set RQLObject = Server.CreateObject("RDCMSAsp.RdPageData") mydate = RqlObject.DecodeDate(myDate) response.write mydate & "<br>" 'converts a date (floating point number) into a serial date ....that can be understood by humans ; - ) %>
If you would like to learn more about converting date values in RedDot CMS, check out this article with code examples.
sendXML function
In order to enhance the overview of the code in your applications you might want to have an area where you just place the RQL functions and another area where you implement the logic. But even the execution of the RQL statements can be excluded in a seperate function. Of course this is not that much but at least we save a few lines of code.
function sendXML (XMLString) set objData = server.CreateObject("RDCMSASP.RdPageData") objData.XmlServerClassName="RDCMSServer.XmlServer" sendXML = objData.ServerExecuteXml(XMLString, sErrors) if sErrors <> "" then response.write "Errors occured: " & sErrors & chr(13) & XMLString & "<br>" end if objData = NULL end function
If you find any errors or have questions, please just leave a comment and I’ll try to help. If you’re interested in more RQL related articles then….right…send us some feedback.
Have fun with RQL!