I think it’s time to rock out with another dotCMS blog, and dig into some basic stuff that can be very useful to people getting started in the content management system. There was a topic recently on the mailing list that was asking about where to look to see some examples of macros, and where you can save your own. This looked to be a good topic to cash in on (speaking of cash, wanna loan me some?).
In dotCMS, a macro is basically like it is in other applications: it’s a collection of code one calls to reproduce complex processes in a simple, and straightforward fashion. You know, to help stupid people out. To put it in other terms, it’s effectively what one might call a function in other languages. You give it a name, set parameters it can take, and define some output. dotCMS comes out of the box with a lot of macros you can readily use, sometimes without even realizing it. These include things like the commonly used pullContent(), and fancier tools like videoPlayer(). Naturally, dotCMS has a list of these built in macros, and how to use them. If you want to take a look at example code, the built in macros are stored in /[dotcmsroot]/dotCMS/WEB-INF/velocity/dotCMS_library.vm. Don’t mess with those though, because odds are you’ll break stuff. Just trust me on this.
There are a couple ways to approach writing your own macros. The first is to write a second .vm file, and store it with the default one in the velocity folder. It will be loaded when the server starts, but requires a server restart when you change or update them, because they are cached in the system when it starts. Conventionally, the file name dotCMS_library_ext.vm is recommended. By convention, I just mean that’s what the dotMarketing programmer folks have recommended to me. The other way is to use a static container, which you include first thing in all the templates you want the macros to be available to. Macros edited and saved this way do not require server restarts to use, but naturally you must make sure you’ve included the container in EVERY template where you suspect your macros might be used (and also ones where they might not. Trust me, never underestimate the stupidity of your users). Neither method is right or wrong, and you should just choose the way that fits your development style best. I’m still looking for a solution that would qualify as chaotic neutral, however.
Okay, so naturally you need to have something of a working knowledge of Velocity code to write a macro, so if you’ve never taken the time to learn some, I suggest you go do that. Mr. Falzone has talked about this issue, so go get yourself some learnin’ and stop trying to run before you can walk. Now, get off my lawn. If you already know Velocity stuff, go anyway, he’s a nice guy and worked hard, so you owe it to him to read it and pretend like you’re new to the subject. Don’t worry, it’ll be our little secret. But, assuming you understand the basics, this should be pretty straightforward. So, starting up, we need to define the macro. I’ll use as an example the macro I wrote that pulls in a list of events from the calendar by a tag:
So, we start by calling the macro() function, naming it, and giving it a list of variables to expect. You can have more than one variable, just list them one after the other (no commas or anything). As you can see, before I open the macro, I list a couple variables in comments that aren’t required, but can be set before you use pullEventListByTag() and they’ll be pulled in later. Next, I’m going to set three variables that I’ll use when querying for events, then I’ll build out the query and set it as a variable, and set how I want it ordered (date1 is the event start date).
Okay, next up I’m going to check for those optional variables, and if they aren’t set, it will give some default values. After that, I’ll call the pullContent() macro (as you can see, you can call other macros within macros), and save the results in its own list variable.
That takes care of the heavy lifting. Next I’ll start the output. In this case I’ll build out a <div> to hold the contents, pump out a header, and start a standard foreach() loop for the results in $eventMacroList just as we would when using the pullContent() macro like any other time. I told you this wasn’t hard.
And believe it or not, that’s it. Once this is saved and initiated in the manner you choose, you can call your custom macro with the parameters you’ve set, and it will execute the code. In this case, you could call pullEventListByTag(”football”) to return all events tagged football. On another page you could call pullEventListByTag(”baseball”) and get a different set, but still get the same structured output. Such is the nature of macros. Any process you would need to do over and over again, or need to simplify for less savvy users are prime candidates for macroification. In simple terms, this example is nothing more than a macro to automate a pullContent() call and foreach() loop. If you look at the default macro file in dotCMS, you’ll see how much more complex you can get with them.
So, the complete macro for this example would be as follows. Feel free to copy and modify it to fit your own needs, or to play around with to get used to the process. I’d be happy to see how you improve or modify it. You can also discuss it in the forums, or share your own creations.