Vacation Learning – PHP and Smarty Templates

I’m on vacation this week and next week. Since I rarely have time to learn anything technical (or blog for that matter anymore), I thought I would take some time during my time off to learn something new around development.

We have a system at work that is essentially a small portal. The core of it was written by me to learn PHP about 8 years ago and has been augmented by me and one other guy at workKeith and I over the years. Over that time, as we added new functionality to it, I used it to experiment with other languages as I was learning it. Other pieces were written in Java out of convenience. In total, we have pieces written in PHP, Java, Python, and PERL.

As I usually use this system to learn new things, I figured it would be a good candidate to use to learn how to use the Smarty templating system for PHP. I became interested in this templating system after working with Eventum over the last few weeks and figured that if I am going to do further work with Eventum, it would be helpful to understand the templating framework it uses.

So I’ve started using the system to take our 8 year old PHP code base and separate some of the presentation logic out. Smarty is pretty flexible and easy to use at a high level (I haven’t gotten into any of the really advanced stuff yet).

Here’s an example of how nicely the use of a templating system simplifies your code. Take this example, which enumerated entries from our internal wiki via an RSS feed into a section on the home page:

 function getWikiEntries($url) {
$theHTML = "";

$rss = fetch_rss($url);

$theHTML .= "

"; $theHTML .= "";# foreach over each item in the array.
 # displaying simple links$rowCount = 0;
 $className = "modifications-evenrow";foreach ($rss->items as $item ) {if (($rowCount % 2) == 0) {
 $theHTML .= " "; } $theHTML .= "# truncate item title to 28 characters
 $myTitle = $item['title'];if (strlen($myTitle) > 28 ) {
 $myTitle = substr($myTitle, 0, 28) . " ...";
 }$theHTML .= $myTitle;
 if (($rowCount % 2) == 0) {
 $theHTML .= "  ";
 } else {
 $theHTML .= "";
 }
 $rowCount++;if ($rowCount == 20):
 break;
 endif;
 }$theHTML .= "

<table cellspacing="0" cellpadding="0" align="center">
 <tbody>
 <tr>
 <th class="header-title" colspan="2">"; # get the channel title and link properties off of the rss object # $title = "Recent Wiki Entries"; $link = $rss->channel['link']; #$theHTML .= "$title"; $theHTML .= "$title   <a href="$url"><img alt="" border="0" />"; $theHTML .= "</th>
 </tr>
 </tbody>
 </table>

<table cellspacing="0" cellpadding="0" align="center">
 <tbody>
 <tr>
 <td class="modifications-sectionheader" colspan="2"></td>
 <td class="modifications-data">"; $theHTML .= "<a title="" href="$item[link]">";</a></td>
 </tr>
 </tbody>
 </table>
 "; return($theHTML); }

I’m sure you can appreciate how hard this would be to maintain, and all of the cruft that has accumulated over the years …

Now take the simplified version (sans error checking), written today in about 10 minutes:

function getWikiEntries($url) {
$rss = fetch_rss($url);

$template = new TemplateEngine();

$firstColumn = array_slice($rss->items, 0, 10);
 $secondColumn= array_slice($rss->items, 10);

$template->assign("firstColumn", $firstColumn);
 $template->assign("secondColumn", $secondColumn);
 $template->assign("link", $rss->channel['link']);

return($template->renderString("wikiEntries.tpl"));
 }

… along with its corresponding Smarty template:

{section name="entries" loop="$firstColumn"}{/section}

<a title="{$secondColumn[entries].title}" href="{$secondColumn[entries].link}">{$secondColumn[entries].title}</a>
 <table width="80%" cellspacing="0" cellpadding="0" align="center">
 <tbody>
 <tr>
 <th class="header-title" colspan="2">Recent Wiki Entries <a href="{$link}"><img src="{$applicationURL}/images/rss.png" alt="" border="0" />

</tr>
 <tr>
 <td class="modifications-sectionheader" colspan="2"></td>
 <td class="modifications-data"><a title="{$firstColumn[entries].title}" href="{$firstColumn[entries].link}">{$firstColumn[entries].title|truncate:28:" ..."}</a></td>
 </tr>
 </tbody>
 </table>

I don’t know about you, but I think thats quite a difference in maintainability. I’d much rather modify the html in the template than in the original function. Not only that, but the code is actually code, not a bunch of code with a lot of simply horrid markup stuck in the middle of everything.

I’m pretty impressed with how much I’ve been able to use in a short amount of time this week. The libraries are obviously thought out and ramp up time for me was really minimal. I like libraries like that. It also addresses something that has annoyed me for a long time. Embedded HTML is a pain to maintain and I’ve dreaded going into this over the years just because of that.

At some point, I’ll investigate what it takes to write custom plugins, a functionality that the libraries also support.

I think I’ve been able to get a really good start at getting something maintainable. My goal over the next few of weeks is to templatize the whole system, then start taking the non-PHP pieces of the system and rewrite them in PHP. I’ll also add the ability to change configuration in one place, so that we can cut some of the pain that we have in keeping things maintained down – and perhaps be able to install the application in other places.

Should be fun. I’m definitely feeling productive over the past few days. I’ve always liked working in PHP over other languages. I definitely have to do work like this more often.

LDAP Enabling The Eventum Defect Tracking System

Due to a recent reorg, I have the opportunity to replace our defect tracking system, which has quite a bit of really wasteful process baked into the tool, with a new one. I’ve been looking at defect tracking software for a while, and chose Eventum, an open source project by MySQL AB for a number of reasons, some of them including:

  • Its open source
  • Its written in PHP, so I don’t have to worry about messing with fastcgi, mod_perl, or mod_python
  • It is extensible (you can add custom fields, etc)
  • It uses MySQL, rather than SQLLite or something like that, so we can integrate it into the rest of our home-grown build software
  • It supports email integration. While we won’t be using this right away, we’ll be implementing it in a later iteration
  • Its simple to use, with a very simple interface, once you get use to it. Everything is essentially on one screen.
  • It has time tracking, along with some basic reporting built in

One thing it doesn’t have built in is LDAP authentication. I wrote a previous article about all of the work we’ve done to integrate both our home grown applications and a few open source applications in with our LDAP store, to minimize the management of multiple passwords across systems, so this was very important to me. I started with many, many Google searches to see if someone else has done this, only to hit one dead end after another. At first I was being lazy and decided to just forget about it. One system not tied to the LDAP tree isn’t that big of a deal, but then my perfectionism set in. Why would I settle for that when LDAP authentication should be really easy to integrate into an Open Source package?

So I decided to spend a few hours to get it working. Since I had no success finding an implementation, I figured I could do my part and post what I have. There are a couple of caveats that I want to throw out before we actually get to the code though:

  1. It isn’t done “right”. This is all extra work for me, so I got enough done so that it would work. The right way to do this would to refactor the auth stuff out into a workflow like hierarchy that could be pluggable (see this post in the eventum mailing list). I’ll get to that someday, but right now this solution hacks the auth module to get authentication working.
  2. LDAP Settings are not configurable through the interface. I don’t have time for that, so a set of defines at the top of the LDAPAuthenticator class contains all of the configuration information for the LDAP server. Bummer, but like I said, I’m on a schedule.
  3. Users still have to be added to the Eventum database – they are not added automagically when they log in. I want control of who is in the system, so I’ve elected to leave this functionality out and just do authentication.

With these three caveats in place though, given my experience looking around for this stuff, at least this code works and will be able to be used by others. Its a starting point – which is more than is out there today. Anyone is free to use this and take the time to do it right. With that said, I’d love to receive updates if someone actually takes this up. For now though, this works for me.

So, now to the code. I wrote a small PHP class called “class.LDAPAuthenticator.php. There are two functions in it. Because Eventum uses email address as the login, we need a way to get the full user DN from the email address. This is what the email_to_dn function does. Given an email address, it returns the full distinguished name of the user. This is called by the main class function, ldap_authenticate. The ldap_authenticate function takes the same arguments as the class.auth.php function isCorrectPassword, which consist of the email address and the password. It binds to the LDAP authentication tree using the full DN of the user and the password supplied. If authentication is successful, it returns TRUE, otherwise it returns FALSE, just like the isCorrectPassword function used to validate the password from the Eventum database.

The code looks like this:

# Change these values to access another LDAP server.
define("LDAP_PORT", 636);
define("LDAP_HOST", 'ldaps://ldapserver.example.com:' . LDAP_PORT);
define("LDAP_BIND_DN", 'PUT THE BIND DN HERE');
define("LDAP_BIND_PASSWORD", 'PUT THE BIND PASSWORD HERE');
define("LDAP_SEARCH_DN", "PATH OF THE TREE TO SEARCH FOR USERS");

class LDAPAuthenticator {

# Look up a users full distinguised name from
# their email address, since Eventum uses
# email address as the login name.
function email_to_dn($emailAddress) {
$returnDN = "";

$server = ldap_connect(LDAP_HOST);

if ($server == FALSE) {
return($returnDN);
}

ldap_set_option($server, LDAP_OPT_PROTOCOL_VERSION, 3) ;

$ldapbind = ldap_bind($server, LDAP_BIND_DN, LDAP_BIND_PASSWORD);

# verify binding
if ($ldapbind) {
# find the user based on the entered email address.
$result = ldap_search($server,
LDAP_SEARCH_DN,
"(&(mail=$emailAddress))",
array("dn"));

$info = ldap_get_entries($server, $result);

# if we actually got a value back, return the users DN
if ($info["count"] > 0) {
$returnDN = $info[0]["dn"];
}

ldap_unbind($server);
}

return($returnDN);
}

# Authenticate with the LDAP server. Function returns true
# if authentication was successful, false otherwise.
function ldap_authenticate($email, $password) {
$returnValue = FALSE;
$userDN = LDAPAuthenticator::email_to_dn($email);

if ($userDN == "") {
return($returnValue);
}

$server = ldap_connect(LDAP_HOST);

if ($server == FALSE) {
return($returnValue);
}

ldap_set_option($server, LDAP_OPT_PROTOCOL_VERSION, 3) ;

$ldapbind = ldap_bind($server,
LDAPAuthenticator::email_to_dn($email),
$password);

if ($ldapbind) {
$returnValue = TRUE;
ldap_unbind($server);
}

return($returnValue);
}
}

Save this file as class.LDAPAuthenticator.php and put it in your Eventum includes directory. Modify the define statements at the top to contain your LDAP server information.

Now, to use it. Go to your Eventum includes directory and add the following line to the top of the class.auth.php file:

require_once(APP_INC_PATH . "class.LDAPAuthenticator.php");

I have this at the end of all of the rest of the require statements.

Now, replace the isCorrectPassword function in class.auth.php with the following function:

 /**
* Checks whether the provided password match against the email
* address provided.
*
* @access public
* @param string $email The email address to check for
* @param string $password The password of the user to check for
* @return boolean
*/
function isCorrectPassword($email, $password) {
return(LDAPAuthenticator::ldap_authenticate($email, $password));
}

… and VOILA. You can now authenticate off of your LDAP tree.

Now, I know it isn’t pretty, hacking the code directly – but it works, and its more of a starting point than I can find anywhere else. I hope its useful to others. Again, if anyone takes this further and does it “right”, I would be really happy to get a copy of the modifications.

One more thing – don’t forget to require SSL on the URL to your Eventum installation by using the SSLRequireSSL directive in your Apache server. You don’t want these passwords floating around in the clear across the network.

Download the Eventum LDAP hack here and happy authenticating.

WordPress 2.1.3 released.

Version 2.1.3 of the WordPress blogging platform has been released and is available for download. According to the WordPress blog, this is a security release that “includes fixes for several publicly known minor XSS issues, one major XML-RPC issue, and a proactive full sweep of the WordPress codebase to protect against future problems”.

I’ve upgraded, and so should you. Take a couple of minutes to do this upgrade, as the possible consequences aren’t worth the humiliation. 😉

Mac Software I’m Finding Useful

I thought I’d take some time to sit down and document the tools I’ve been using lately as I continue my acclamation into the MacIntosh world. These are tools that I’ve found really useful over the last six months or so.

  • The Camino Browser – hands down the best browser I’ve found for the Mac so far. It’s my default browser.
  • Ecto – Mac Native application for writing blog entries and posting them to your blog. Supports Blogger, Blojsom, Drupal, MovableType, Nucleus, TypePad, and WordPress among others. Doug referred to MarsEdit as another alternative, but Ecto fits the bill for me perfectly. It includes spell checker, Amazon Web Services integration, templates, preview – really everything you would want in an offline authoring tool.
  • Vienna Newsreader – Vienna is an open source RSS reader for the Macintosh. It is quite comparable to FeedDemon, which I used on Windows, but I like it a lot better. This tool has become one of the things I use daily in order to keep up with things
  • Snap N Drag – Screen capture utility I mentioned in previous posts. I use this all the time as well. Excellent tool.
  • BBEdit 8.5 – BBEdit is an HTML editor for the MacIntosh platform. Its the only thing I’ve found comparable to HomeSite for the Macintosh. I’m using a trial version of this application right now, but there is a good chance that when the 30 day trial ends, I’ll be buying a copy. It makes HTML authoring a hell of a lot easier than Emacs.
  • UberCaster – This is podcasting software. I have a license for it, but I haven’t had the time to muck about with it. By far the easiest podcasting software I’ve seen so far for the Macintosh. The software is currently in beta.

Some additional software I’m looking at that looks useful, but I don’t have need for it yet:

  • Xyle Scope – CSS exploration tool. I’ve messed around with this a bit and it looks really interesting. I haven’t found another tool like it so far. Allows you to explore CSS and how the styles are resolved on your page.

I’m still looking for good image editing software that doesn’t cost a bajillion dollars (like Photoshop) and doesn’t require X-Windows to be installed. If anyone has any suggestions, I’d be happy to hear them.

WordPress 2.0.5 Released

The folks on the WordPress team have released version 2.0.5 of the WordPress Blogging Application. This release includes around 50 bug fixes one of which was a missing index on the posts table. I just upgraded and the site performs much better now. I had always thought that the site ran a tad bit slower after the 2.0 upgrade, but for some reason I just figured 2.0 was doing so much more than the 1.x versions. Didn’t even think of looking at table indexes.

Mark Jaquith has also put together his list of change files and corresponding archives containing only the changes from 2.0.4 to 2.0.5, along with a patch file to upgrade your stuff directly. I opted to download from the WordPress site.

In any event, according to the release announcement, there are some security fixes in this release as well. As I do with every release of WordPress that contains security release, I am reminding you not to be lazy and get your site upgraded as soon as you can. The performance improvements alone are worth it.

Now … off to see if they fixed that “posting from Flickr mangling CSS thing” …

Value Stream Mapping Software

I’m looking for software that does Value Stream Mapping. As with mind mapping, this process is an extreme pain without a tool to do it. If you know of any good software (or component add ons for existing software like Visio), please leave a comment on the blog. Of course, the first preference is free, but I’d love to look at commercial software as well.

More on Mind Mapping and MindManager

I’ve been playing around with MindJet MindManager over the last week or so and I have to say, overall I really like it. Mindmapping provides a great mechanism in getting your thoughts down on paper and establishing relationships between different concepts, especially for someone who suffers from “chronic editor” syndrome such as myself.

I’d love to post some examples of some of the things that I have been working on, but the only real “work neutral” mindmap I have available is the one I previously posted. Some really good examples can be found in the mindmaps that Cote produces. These are some really good examples of the complexity that can be represented using this technique.

I had first read about mindmapping quite a few years ago in the book Quantum Learning: Unleashing the Genius in You by Bobbi Deporter (with Mike Hernacki). Deporter and Hernacki describe the Mind Mapping technique as “a whole brain technique using visual images and other graphic devices to form impressions”. The key piece of this, for me, has been the connection and breakdown of different concepts into sub concepts. The graphical nature of a mind-map, coupled with the distilling of the key concepts and relationships and visual representation, have allowed me to retain much more information while taking notes over the past week than I have previously experienced.

I had attempted mind-mapping when reading Quantum Learning, but the extremely manual process (actual drawing) turned me off immediately. For me, it just seemed like too much work.

That’s where Mind Manager comes in. With a few natural keystrokes you can string all of these concepts together, attach images or URL’s to the key concepts for further reference material, and flag concepts as priorities or something to pay attention to. The additional benefit of a tool to do this stuff is the ability to dynamically refactor your mind maps without having to throw away your piece of paper and recopy everything. The refactoring of these concepts has been something that I have been doing quite a bit.

The folks at MindJet were nice enough to give me complimentary licenses for both the Macintosh and Windows environments. Since buying a Mac in June, I have decided to use it exclusively at home in order to learn as much about the environment as possible (and, of course, to justify the investment). So, I have had the opportunity to work on a few mind maps across the two environments. There is no ‘import’ or conversion necessary. I store the maps on my thumb drive, work on them at home, take them to work, and they just load and are ready for continued editing on the Windows platform.

There are some differences between the two versions of the product. The Windows version has quite a bit of Microsoft Office integration. You can export your mind maps to Visio, Word, Excel and even Microsoft Project, in addition to JPG and PNG image formats and PDF. Both versions allow you to add task information to map nodes, including flagging nodes as resources and flagging them as quarter, half, three quarters done, as well as completed. I have not experimented with taking these types of mind maps and exporting them to project, but I’m assuming these move along with them (I can mess with it later and validate this).

The Macintosh version has a more limited set of export formats. JPG and PNG are supported along with multiple flavors of RTF (Word, TextEdit) and PDF.

For me, the use of this tool over the past week has been a really positive experience – on the Macintosh. The Windows version has some pretty major performance issues that are being talked about in the support forums as well as being addressed specifically by the Vice President of Engineering on the companies blog.

The Windows machine that I am running MindManager on has 2G of memory and 80G of hard drive space. When docked, I run at a pretty high screen resolution (1280×1024 – maybe even higher). Docked, the software runs well enough to do the work I need to do as another connected concept hits me on some of the things I am working on.

The strange part is that as soon as I undock and run in ‘laptop’ mode at the standard 1024×768 resolution, performance drops to the point where the software isn’t even usable. I’m not sure why this is the case, but at a seminar the other day with the Windows laptop, I was unable to take notes using the software whatsoever, as the software began exhibiting the symptoms mentioned in the above links.

Overall, the technique of mind mapping is proving extremely helpful to me. As mentioned earlier, using the technique has increased the retention that I am experiencing while thinking through problems. The MindManager software is excellent – on a Mac. The Windows version needs some work to fix some of the performance challenges that I am experiencing.

The price tag for the software is not the cheapest in the world either. A single user license for MindManager 6.0 Pro weighs in at a whopping $349, with the Basic and Macintosh versions available at $229. The question then becomes is the price tag worth the value received from the software. While I’m receiving a ton of value from using the software, the price of a single user license would definitely stop me from even taking the time to try it in the first place. While the company does make trial software available (both a 5 day express trial with no registration required and a 21 day “premium trial” of which the premium is registering with the company), I rarely “do” trials on products in this price range for the fear of getting addicted to them and having to pay for them.

So the real question for me as I use the software further is whether I will buy it. Time will tell. I like to (and see it as an obligation) to support software I find useful with my wallet. The only real guarantee that useful software will continue to be available is if there is a community behind it, or, in the case of commercial software, people actually buy it. Once the “newness” of the software wears off, we’ll see if I continue to see value in the process and whether I keep using the software. At the point that I find it indispensable, I will definitely shell out the money to show my support for the product.

And when that happens, you’ll definitely be the first to know.

Related Links

Using a Mac – A MindMap

Photo by rbieber

Experimenting with MindJet MindManager, an application used to create mind maps. Tom the Architect has talked to me about mind maps a bajillon times, but I have been reluctant to start using them because the only "free" program was a Java app. The folks at MindJet shot me a complimentary copy of their software and I’ve started using it. Sat in a meeting yesterday and walked away with more content than I’ve ever walked away with note-wise. Excellent software.

This is something I used just to play with the software. These are things I like about the Mac, as a new user.

I’m really liking the complimentary copy of MindJet MindManager I received the other day from the folks at MindJet. I have been intrigued by mindmapping since first reading about it in a book and later watching Tom the Architect produce them as a form of meeting notes (using FreeMind). Lately, I’ve been watching Cote produce a slew of them. Playing around with the software, it makes note taking so much easier.

I just might buy a copy at some point to show my appreciation for the productivity gains I believe I will receive just from having this software installed on my machine.

As I use it more in “real life” I plan to write more about it. Mind mapping definitely puts you in a different state of mind in a meeting. I’m one of those people that has a hard time taking notes because I wind up editing sentences while people are talking rather than getting the data down. This process removes me from that mindset all together. I can see all sorts of uses for this to increase my productivity.

Screencast Demo of Castblaster Podcasting Software

If you’ve been looking for a tool to make podcasting much easier than using Audacity, you might want to check out Castblaster. I’ve used it for quite some time and each release it just gets better and better.

While browsing the Castblaster forums, I came across this screencast put together by Troy of the Rutters Ramblings podcast that shows a pretty complete picture of what Castblaster does.

If you don’t feel like downloading the software, but are curious as to what you could get from it, check out the screencast. Yes, it can be that easy.