use MT::Everything, Part 2: An Events Calendar
Still high off the success of using Movable Type for an online newsletter, I decided I could use MT for OKMensa's event calendar as well. This was more difficult, but the benefits were huge.
I started by creating a new weblog, Calendar, and assigning all the authors to it. I turned off most of the index templates, leaving the main index and the stylesheet on. I added some more templates, but more on those later. I set it to order entries ascending, and the preferred archive type to Individual. I set it to generate Individual and Monthly archives, and I created a custom Archive File Template for each just like I did with the Mensokie.
MT has the <MTCalendar>
tag for creating a monthly calendar. I put one of these calendars in the main index. This would be the main page of the calendar and always show the current month's events. I also wanted links at the bottom of the page to the next and previous months. That's where things got tricky. I tried this bit of code, but it doesn't work on a main index -- it only works in an archive context. I decided that, to handle this problem, I was going to need to bring out the big guns. And I knew just who had them.
Brad has created some very powerful plugins for MT. For this particular problem, I installed the PerlScript plugin. It took some fiddling to get it right, but I came up with this bit of code:
<table width="100%" cellpadding="10" cellspacing="0" border="0">
<tr>
<MTArchiveList archive_type="Monthly" lastn="12">
<MTPerlScript>
if (1<$MTArchiveDate format="%m"$> == 1<$MTDate format="%m"$> - 1)
{
print "<td align=\"left\" bgcolor=\"#ffffff\">\n";
print "<a href=\"<$MTArchiveLink$>\">« <$MTArchiveDate format="%B %Y"$></a> \n";
print "</td>\n";
}
</MTPerlScript>
</MTArchiveList>
<MTArchiveList archive_type="Monthly" lastn="12">
<MTPerlScript>
if (1<$MTArchiveDate format="%m"$> == 1<$MTDate format="%m"$> + 1)
{
print "<td align=\"right\" bgcolor=\"#ffffff\">\n";
print " <a href=\"<$MTArchiveLink$>\"><$MTArchiveDate format="%B %Y"$> »</a>\n";
print "</td>\n";
}
</MTPerlScript>
</MTArchiveList>
</tr></table><
Here's what's happening: I use an <MTArchiveList>
to loop through the last 12 months of monthly archives. For each archive, if the month of the archive is one less than the current month, I print a link to it. Notice I put a 1 in front of each tag that outputs the month. MT outputs month with a leading zero, which Perl will interpret as an octal number. So I'm essentially adding 100 to the month number before doing the comparison. I then do basically the same thing again, this time looking for the month that is one greater than the current month. These have to be in separate <MTArchiveList>
loops, because MT loops through archives in descending order. If you try to do it with one loop, the next month link will appear before the previous month link.
On the monthly archive pages, I did a calendar just like the one on the main page. The links at the bottom were easier because I could use <MTArchivePrevious> and <MTArchiveNext> to generate them.
The individual event pages are pretty basic, displaying the date, time, and other general information about the event. When we create an event, we set the timestamp to the date and time when the event occurs, and we enter a word in the keyword field to use for the short name.
Now, at this point we have a basic online calendar much like the one we had before. The only real difference is the links to individual events are not Javascript popups and you cannot follow the "Next Month" links out to the year 2145 and beyond. And, while those are good things, I wanted more.
One of the services we offer to members is a mailing list you can sign up for and get reminded of upcoming events. Since we've had that, Angela and I (but mostly Angela) have been sending out the reminders the day before. Problem was, we didn't have anybody to remind us. I knew there had to be a way to automate this process.
I found this example at ParanoidFish. Using this as a starting point, I created a new index template named "Email Reminder" and set it to create an email.txt file.
Now, unlike the example, I wanted the next days entries, not the previous day. So, it was back to Brad's site to download the SQL plugin. This allows you choose a set of entries based on your own custom SQL query. The following gives me the entries I want:
<MTSQLEntries query="select entry_id from mt_entry where TO_DAYS(entry_created_on) - TO_DAYS(NOW()) = 1 AND entry_blog_id = 3">
...list entries here...
</MTSQLEntries>
When we create the entries, we put directions and a MapQuest link in the extended entry field. This information is not posted on the site for privacy reasons. We do, however, include it in the e-mail we send out.
What I had at this point was the body of my e-mail -- I still needed to automate the process of sending it out. Much like the example, I installed the MT-Rebuild script and wrote a short shell script:
#!/bin/sh
/path/to/MovableType/mt-rebuild.pl -mode="all" -blog_id=3
if [ -s /path/to/file/email.txt ]
then
fold -s -w 76 /path/to/file/email.txt > /different/location/email.txt
mutt -x -H /different/location/email.txt
echo "E-mail sent"
else
echo "No E-mail sent"
fi
I did mine a little different than ParanoidFish, and here's why: I found that the mail application, mutt, has a "draft" option. This allows you to pass it a file with both header information and the message. This way, I can specify who the e-mail is from, rather than it being from the generic user mutt would otherwise send it as. Also, since I'm creating these headers through MT, I can customize the subject line to have the date of the events. Little things are important to me.
Finally, I set up a cron job on my host to run this script every morning. It will rebuild the index files, and if the email.txt file is not empty, it will send an e-mail to the mailing list. An added benefit is that, since the indexes are built every day, the main page of the calendar is always current.
One other feature I was able to implement was iCalendar and vCalendar versions. This allows you to download a file and import the events into Outlook, Palm Desktop, or various other date book programs. This is really easy with MT. Using the example here as a starting point, I created two new archive templates, iCalendar and vCalendar. I then changed my archiving preferences to include those as monthly archives. It took some tweaking, but I was able to get the iCalendar file where it would import into Outlook and the vCalendar where it would import into Palm. If you're interested, here is the iCalendar template and the vCalendar template.
These use Brad's MTRegEx plugin to encode certain values for these formats, and a little bit of Perl to set the datetime stamp. MT returns the time in the time zone you specify for the weblog. iCalendar and vCalendar want GMT. So, I used the PerlScript plugin to convert from local time plus one hour (since the server is in the Eastern time zone and we're in Central) to GMT.
Then, to head off some questions about these files, I wrote a page that describes what they do and how to use them. I put that in MT as an index template, rebuilt, then switched it off so it would not rebuild everytime. This was really just so I would have all the calendar-related pages in one place.
So, there you have it. There are still a few things I would like to do with this. I have an idea for supporting recurring events. And, it might be nice for the main page to be able to switch between the current month, the current week, and the current day. But, I'll schedule those features for another time.