About Adam

Adam Stout works in the technology field and is currently located in San Diego, CA.




Recent Entries


Exporting SVN Change Log in Phing

Posted: Jul 17, 2010
Last night I was working on add a phpDocumentor task to a Phing build script I have been working on.  While Phing offers integration with phpDocumentor as well as some SVN task such as commuting, updating, and exporting, it doesn't have a native way to export the change log which I would like to include in the documentation.  However, one great feature of Phing is how easy it is to expand.  I wrote this little ad-hoc task to export the SVN history to a file which I then include in the documentation.

Here is the code if you'd like to add it to your build scripts:

<adhoc-task name="svnlog">
svnLog extends Task 
setFile($file) { 
$this->file $file
setSvnPath($svnpath) { 
$this->svnpath $svnpath
setRepositoryUrl($repositoryurl) { 
$this->repositoryurl $repositoryurl
    private function 
$cmd $svnpath " log " $repositoryurl " > " $file;
$cmd "\n";
main() { 
$this->writeSvnLog($svnpath $this->svnpath$repositoryurl $this->repositoryurl$file $this->file);

Here is how you call it:
<svnlog svnpath="/usr/bin/svn" repositoryurl="http://rex/svn/${package}/" file="${workingDir}/CHANGELOG"></svnlog>

Deploying PHP with PHING

Posted: Jul 06, 2010
A couple of months ago I came across PHING, a deployment system for PHP.  It seems pretty straight forward to use and really tuned for PHP.  It has tons of extensions to use all the tools a PHP developer would want.  I finally have something that will run on Windows or Linux and will mange deployments on my local box, a prototype server, or my productions servers and all I have to do is put together a little XML config file.

I alike that it is so easily customizable as well.  For instance, my production server runs PHP in cgi mode so I can't change PHP settings in the .htaccess fiel so I have to have a php.ini file in every directory that has PHP to change these settings (on a side note, I'm looking forword to getting php5.3 installed which introduces the .user.ini setting which works like a .htaccess just for PHP).  I really didn't want to maintain serveral copies of the same php.ini file so I wrote a little adhoc-task which expands PHING to copy a single file to every directory in the tree.  A couple of lines of PHP in my PHING build.xml and I'm up and running.

    <adhoc-task name="copyrecurse">
    class copyRecurse extends Task 
        private $file;
        private $todir;
        private $file_name;
function setFile($file) { 
            $this->file $file
function setToDir($todir) {
            $this->todir $todir
private function getDirectoryTree($BASE_DIR,$LEVEL=1){
            $THIS_DIR array_diffscandir($BASE_DIR), array_merge(array( ".""..",".svn")) );
            foreach( $THIS_DIR as $DIR ) {
                    copy($this->file$BASE_DIR."/".$DIR "/" $this->file_name);
            return true;
        <br>        function main() { 
            $this->file_name basename($this->file);
            $this->getDirectoryTree($BASE_DIR $this->todir);
    <copyrecurse file="${workingDir}php.ini" todir="${workingDir}/>

I'm looking forward to using PHING in the future and integrating some of the tools it gives me access to.  Hopefully more of us will start using it to help ensure it is maintained going forward.

Annoying CSS

Posted: Jan 24, 2010
I've spent the last few evenings trying to update the layout of my site to handle resizing better.  Before it was hard-coded to be 972 pixels wide.  This looked fine on my laptop (and I'm hoping on most other people's computer's) but since I bought I 24" wide screen monitor I realized there was lots of unused space that could really be used by my photo gallery.  On the left, you can see what the gallery looked like before my changes.  There was only a fixed number of pictures per row which once again was fine on my laptop but left a lot of unused space on larger monitors.

To my point, I tried to allow the CSS template to flow with the center expanding but I just couldn't get it to work right.  I need to have three variable height columns to work but that just doesn't seem possible.  This is the closest I found to what I wanted but it couldn't use a background image for the side columns (other than that, it would have been fine).

I ended up using the old borderless table technique.  I wanted to stick to CSS only, but like I said, I don't think it is possible (I though you could use the new table emulation in CSS but that isn't support everywhere and is basically just using a table anyway).

Moral of the story, sometimes you should just use the simplest approach instead of wasting time trying to fancy.  On the plus side, you see on the right the same photo gallery as on the left but now it is stretched out and can take up more of the screen space which is a good thing for the galleries that have hundreds of pictures as well as when viewing all the photos with a certain tag (which is a recent feature added to the gallery).

Photo Gallery Update

Posted: Jan 14, 2010
In April of last year, I migrated my Picasa based photo gallery to use Flickr instead.  I like the Flickr's API much better than the crap Google offers for Picasa.  In addition to the API Flickr offers unlimited storage of pictures for about the same price as a few GB of storage with Google (at the time at least).  I believe they have since lowered their prices so you can get unlimited storage with Flickr or 80 GB with Google.  If Google makes some enhancements to the API, I may end up switching back.

To the point, with nearly 70 photo albums, the Flickr API was a little too robust to use real time.  To get around this, wrote a small MySQL database to cache all the data I need locally (still hosting the pictures on Flickr).  This has greatly improved the load time of all the pages.  For instance, the main gallery page now loads in .4 seconds instead of the 20+ seconds it was taking before.  While the API had everything I want, not everything was in the right call, so I had to make several calls per page instead of just one large call to the API.  This really slowed things down.  Now I just call a single MySQL query (that still needs to be optimized).

I'm also taking the opportunity to clean up the accordion menu by switching from a one off script to a YUI based solution.  This change will allow me to do some additional expansions in the future to allow for more groupings and possibly some more display options.

Let me know what you think
I posts over the last few months I have mentioned converting some of my web sites to the Yahoo User Interface (YUI) Library. If you haven't looked at YUI, you should. In just a few minutes I was able to replace the the static blog entry calendar (seen to the left) with a dynamic calendar (on the bottom right) that allow users to scroll through all the months my site has been on line (about two years now).

This was done with the Calendar widget of YUI. It would be nice if there were a few more examples and perhaps comments in the documentation like PHP.net uses, but over all the documentation meets my needs (and there are some good examples to get you going).

Back to the point, YUI provides access to some really powerful widgets including drag and drop, auto-complete, tabs, and a rich text editor all with just a few lines of code. On one site I replaced four libraries that I had assembled from around the web with one call to the YUI libraries. I can also rest a little better knowing that my javascript is supported, maintained, and tested for all the major browsers (and will be moving forward based on the sites that use YUI).

I've heard about Google's Web Tool kit but I believe that is only for Java apps. It is nice that Yahoo realizes there are other languages besides Java and help you write your app in what ever language you want by giving you everything you need in JavaScript.

New Photo Gallery

Posted: Jul 31, 2009

Well after quite some time of talking about it, this week I finally finished my updated photo gallery based on Flickr instead of Picasa. There were two main reasons for the change:

  1. Better API - Google provides a well documented API, but I challenge you to build a site like Picasa with it... you can't. Google puts out an API to pretend like they are a benevolent ruler of the web, but in reality they are the great evil. Flickr's API seems to let you do what ever you want. I'm planning on expanding the gallery to use the geo tags in the photos (which are very easy to add on Flickr's site).
  2. Cheaper - Google uses a price per GB model for charging for space which is cheaper if you have only a small amount of pictures, but Yahoo charges a flat fee for unlimited bandwidth and storage. With Google I could have saved some money if I used "web quality" pictures, but if I upload the full quality pics, Flickr is MUCH, MUCH cheaper. Now I have a full backup of my pictures too.

Check out the new gallery and let me know what you think.
I'm currently in the process of converting one of my web applications from static tables all generated on the server side to a YUI based implementation which uses a lot of JavaScript calls to get the data on the client side to display. This has some distinct advantages but also some disadvantages.

For instance, where I used to use this PHP function to convert a file size (in bytes) to a string that would display nicely:

                     Format Bytes to a human readable format
                     * @param int $BYTES Size in bytes
                     * @param string $SIZE Format to use (k,m,g,t,best)
                     * @param int $DECIMALS Format string to use in
                     * @return string Formated string
                     * @todo Support k-t size
                     * @deprecated Use the MySQL UDF to do this in database
           function byteFormat($BYTES$SIZE="BEST"$DECIMALS=2){
                                    if(substr(strtolower($SIZE),0,1) == "b"){
                                        if($BYTES pow(1024,4)){
                                            $SIZE "t";
                                        } elseif($BYTES pow(1024,3)){
                                            $SIZE "g";
                                        } elseif($BYTES pow(1024,2)){
                                            $SIZE "m";
                                        } else {
                                            $SIZE "k";
                                        case "k":
                                            $FORMATED_DATA number_format(($BYTES pow(1024,1)),$DECIMALS) . "kb";
                                        case "m":
                                            $FORMATED_DATA number_format(($BYTES pow(1024,2)),$DECIMALS) . "mb";
                                        case "g":
                                            $FORMATED_DATA number_format(($BYTES pow(1024,3)),$DECIMALS) . "gb";
                                        case "t":
                                            $FORMATED_DATA number_format(($BYTES pow(1024,4)),$DECIMALS) . "tb";
                                    return $FORMATED_DATA;
I need to now use a SQL function to do the processing. (I could still use PHP, but that would require processing the data more than I want to). I've been doing a lot of work in PL/SQL lately so I decided to write a MySQL UDF to accomplish this instead of a huge case statement. While there are a lot of examples for PL/SQL functions, I had a hard time finding a good example of what a MySQL UDF looked like so I thought I would post this in case anyone else is going through what I did.
                                       ,desiredSize VARCHAR(30)
                                       ,decimalPlaces INTEGER)

    DECLARE formatedString VARCHAR(250) DEFAULT '';

    IF LOWER(SUBSTRING(desiredSize FROM 1 FOR 1)) = 'b' THEN
                                   SET desiredSize = CASE
                                                         WHEN (bytes POWER(1024,4)) THEN 't'
                                                         WHEN (bytes POWER(1024,3)) THEN 'g'
                                                         WHEN (bytes POWER(1024,2)) THEN 'm'
                                                         ELSE 'k'
    END IF;
           SET formatedString = CASE
                                  WHEN LOWER(SUBSTRING(desiredSize FROM 1 FOR 1)) = 'k' THEN CONCAT((FORMAT(bytes POWER(1024,1),2)) , 'kb')
                                  WHEN LOWER(SUBSTRING(desiredSize FROM 1 FOR 1)) = 'm' THEN CONCAT((FORMAT(bytes POWER(1024,2),2)) , 'mb')
                                  WHEN LOWER(SUBSTRING(desiredSize FROM 1 FOR 1)) = 'g' THEN CONCAT((FORMAT(bytes POWER(1024,3),2)) , 'gb')
                                  WHEN LOWER(SUBSTRING(desiredSize FROM 1 FOR 1)) = 't' THEN CONCAT((FORMAT(bytes POWER(1024,4),2)) , 'tb')

    RETURN formatedString;

BTW, in the MySQL documentation it shows the DECLARE statement but doesn't emphasize enough that the DEFAULT is mandatory. It took me a while to figure that out.