Kris Wallsmith

Discussing web development, Symfony and fatherhood.

Jul 5

Doctrine Timestamps and User Timezones

I recently added a “timezone” dropdown to the user preferences screen on a symfony application currently in development. This simple extension to the sfDoctrineRecord class makes it easy to present times from the database in the current user’s timezone.

abstract class myRecord extends sfDoctrineRecord
{
  protected function _get($fieldName, $load = true)
  {
    if ($value = parent::_get($fieldName, $load))
    {
      $column = $this->getTable()->getColumnDefinition($fieldName);
      if ($column && 'timestamp' == $column['type'])
      {
        $timezone = date_default_timezone_get();
        if (ProjectConfiguration::DEFAULT_TIMEZONE != $timezone)
        {
          // shift value to the current timezone
          date_default_timezone_set(ProjectConfiguration::DEFAULT_TIMEZONE);
          $time = strtotime($value);

          date_default_timezone_set($timezone);
          $value = date('Y-m-d H:i:s', $time);
        }
      }
    }

    return $value;
  }

  protected function _set($fieldName, $value, $load = true)
  {
    $column = $this->getTable()->getColumnDefinition($fieldName);
    if ($column && 'timestamp' == $column['type'] && $time = strtotime($value))
    {
      $timezone = date_default_timezone_get();
      if (ProjectConfiguration::DEFAULT_TIMEZONE != $timezone)
      {
        // shift value to the default timezone
        date_default_timezone_set(ProjectConfiguration::DEFAULT_TIMEZONE);
        $value = date('Y-m-d H:i:s', $time);

        date_default_timezone_set($timezone);
      }
    }

    return parent::_set($fieldName, $value, $load);
  }
}

To get sfDoctrinePlugin to use this class instead of the default, sfDoctrineRecord, add the following to your ProjectConfiguration.

// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // ...

    sfConfig::set('doctrine_model_builder_options', array(
      'baseClassName' => 'myRecord',
    ));
  }

  // ...
}

Jun 30
“No one is further from the truth, than the one who has all the answers.” Chinese proverb

Jun 25

svn import: inconsistent newlines

I encountered this error ad nauseum while importing external libraries into my local/offline Subversion repositories:

File ‘/foo/bar’ has inconsistent newlines

At first I was opening each file in Textmate and then “save as”-ing with Unix newlines. This takes way too much time, so I wrote this little PHP diddy:

<?php

// Usage:
// php smart_svn_import.php . http://repo "Initial import"

$command = 'svn import --quiet %s %s -m %s 2>&1';
$command = vsprintf($command, array_map('escapeshellarg', array(
  $argv[1], // path
  $argv[2], // url
  $argv[3], // message
)));

while (true)
{
  ob_start();
  passthru($command, $return);
  $content = ob_get_contents();
  ob_end_clean();

  if (0 == $return)
  {
    break;
  }

  if (preg_match('/^svn: File \'(.*)\' has inconsistent newlines$/m', $content, $match))
  {
    // fix this file
    file_put_contents($match[1], str_replace(
      array("\n", "\r\n"),
      array(PHP_EOL, PHP_EOL),
      file_get_contents($match[1])
    ));
  }
  else
  {
    throw new Exception($content);
  }
}

Jun 20

Swan Song

We are travelling north to Cognac today, then back to Paris Sunday night, then flying to Portland on Monday morning. I promise I’ll get some pictures up soon!


Jun 17

Travel Fatigue

The inevitable has happened: travel fatigue officially set in a few days ago. Six weeks away is a long bloody time. Just comprehending that has been an experience in and of itself.

We drove from our last place, near Najac, to near Biarritz on Saturday, where we’re staying in an old mill of some sort. The house was built in the 1500’s and is right on a small river. The mill itself has been decomissioned — the damn broken in half, the platform over the river turned into a patio — but you can still make out some hints of how it once worked. For instance, the tracks that gates slid up and down in to control the flow of water are still there if you climb down and take a look.

The house is very damp. This is either because the house is built over a river or because of the incredibly humid weather, or (probably) both. The first night here the floor and walls were wet to the touch and the bed sheets were moist. Kind of yucky. The dampness on top of the clostrophobic humidity and the long drive on Saturday add up to some tired and cranky peeps.

Cranky is of course the last thing I want to be experiencing right now. I’ve decided to take the perspective that we have less than a week left here and this is really such a gorgeous country that I need to cherish these last few days.

I don’t anticipate that being too difficult :) The weather is improving tomorrow and we’re going to be spending a day on the beach building sand castles and watching the surfers. My daughter wants to try boogie boarding, which has me day dreaming about her hitting the waves on the Oregon coast, wearing a wet suit of course.


Jun 13

Travelling to the coast today. I’m not sure if I’ll have access to the web down there. If not, I’ll be back in a week!


Jun 8

From the middle of nowhere

I can’t believe my four weeks in Paris went by so fast. But they did, and now we’re holed up in a house 8.5 hours south of Paris, listening to a magnificent thunderstorm outside.

First things first. My time at Sensio was very nice. My primary takeaway would have to be shaking hands with everyone at the start of every day. I haven’t experienced this in the states: I saw a lot of people around the city shaking hands at the start of the day. It’s very human. Much better than just opening the laptop and diving right back in.

Our last evening in Paris featured a dinner brought to you by Rue de Moines, the street we were staying on. I walked with my 2 year old son strapped to my back and picked up a cooked chicken and potatoes from the butcher, some lettuce from the produce stand, some cheese from the cheese shop, and of course some wine from the wine store. The food was all delicious in its own right, but I enjoyed it even more knowing I purchased it all from so many different stores, so close by.

Our drive south the next day was one of traffic, singing and puking. Guess which one was the most fun? Getting out of Paris was a nightmare. It took us about an hour just to get through the traffic we hit coming out of the airport. Our GPS device, which we’ve nicknamed “M” on account if her lovely British accent, was dead-on in estimating our trip at 8.5 hours. We drove through some lively countryside during that time, and some very windy, hilly roads. Unfortunately, neither of my children’s stomachs were up for it. I think I counted three outright puke-fests and a few rounds of dry heaving. Our nanny called it the pukiest car ride she’d ever been on. I couldn’t help but compare it to the Team America puke scene…

We did indeed make it to our destination whole hearty and, for the most part, healthy. Our place is about 9km from the mideval village of Najac, which we visited today (I’ll post some pictures soon). The countryside is breathtaking. There’s a small creek bordering the property that we played in with the kids for awhile yesterday. I built a little dam and had a fleeting fantasy about violating some 500 year old water rights treaty.

In other news, wifi is scarce, so I’m just posting to the blog here over the cellular network ($.02/kb, ugh) and responding to the occasional email. I’ve created local Subversion repositories for the projects in working on, which I’ll be manually syncing with their respective motherships from time to time. Vacation continues, but so does work. C’est la vie!


Jun 1

Two ZendCon proposals

I submitted two 400-character proposals to ZendCon yesterday.

Someone else’s symfony

Taking on development of a symfony application started by another developer can be a daunting task, especially for those not familiar with the framework. This will be a practical exploration of symfony from the perspective of a developer taking on an existing project. Topics will include getting started, automated testing, the anatomy of a symfony request, refactoring and symfony best practices.

I think this is a really juicy topic I’ve never seen covered. The current symfony documentation is geared toward either someone new to symfony starting a new project or someone experienced with symfony working on an existing project. I think the population of devs new to symfony on an existing project could use some luv. This also seems like a new and refreshing way to introduce symfony.

The Community Stack

A vital ingredient to any open source project is a vibrant community. Drawing from his experience as Community Manager for the symfony framework, Kris will examine the makeup of a successful “community stack” and propose three basic layers: devs/users, the larger OSS community, and the society as a whole. How these layers interact and grow will be the focus of this session.

The idea here is to acknowledge the importance of community in an open source project with the same significance you would any other solution stack you depend on. I’ve been working on some meat for each of those three layers, but haven’t had a chance to give this talk yet. Here’s hoping that will change!


May 30

Finally, a day in Paris

My wife and I finally got a chance to experience Paris in leisurely style yesterday. We started in Île Saint-Louis around lunch time and had a very nice meal with a great view of the back of Notre-Dame and a pleasant breeze off the Seine.

After our meal and some coffee we strolled the island while enjoying some ice cream and sorbet, supposedly the best in Paris. We bought some gifts for folks back home and sat by the river, chatting about how fortunate we are to be able to do this.

From there we crossed the pedestrian bridge to the cathedral and walked around the gardens. The front of Notre-Dame is always so busy with tourists, but the gardens in the back are very quiet. We thought about going inside, but the line was crazy long.

We then wandered back over the river, this time to the right bank, and looked around to see where we should go next. The Pompidou Center caught our eye, to put it mildly, so we headed there. The thought of exploring the museum was a bit too much for us at the moment, so we just checked out the ground floor and enjoyed the activity in the square out front.

We checked the map and decided to head to the Louvre next. After a walk through Les Halles we entered the museum grounds through the courtyard, which is a fantastic reveal of the magesty of that building. The fountains around the glass pyramids were very pleasant, especially on a sunny day, and gave us some interesting ideas for a water feature back home.

The Louvre is a huge museum. First thing upon getting tickets you need to decide which wing of the building to visit. We hadn’t done any research, so we went with what seemed oldest: the Egyptian stuff. That direction started off Medieval — we walked around the base of a castle and checked out a dungeon — then we got distracted by traffic signs for the Venus de Milo.

We saw the statue and I enjoyed it as much as any untrained eye could. I’m sure there’s a lot I don’t know about that piece that would have enriched my experience. Then we headed through the grand hall and spent about an hour in the presence of some amazing Renaissance art. By the time we got to the Mona Lisa I was pretty tired, but it was a real privilege to be in her presence.

At the end of the day we felt like we had finally experience Paris, and we had done it in a way that didn’t involve a schedule or too much mass-transit. It was definitely a day I’ll remember for years to come.


View Larger Map


May 29

Willy Wonka’s Nespresso Factory

My most surreal experience this trip was my trip to the Nespresso store yesterday.

When I came up from the Metro I was greeted by the old Opera house, which is gorgeous. I didn’t have the exact address with me, so I checked my iPhone for an available Wi-Fi network. I was able to connect to one called “Google-Guest” and find the store in the maps app.

The store itself was like a cross between Willy Wonka’s chocolate factory, the milk bar from The Clockwork Orange, and a Banana Republic store.

There were two guards on either side of the entrance. The ground floor resembled a very spacious retail store, but instead of clothes there were little espresso machines on pedestals, adorned with tiny little cups. The floor was a polished white, and in the middle of the room there was a brushed steel and glass spiral stairway down to the basement.

The lower level was definitely where the action was. This area had a more library/den quality to it (think: a milk bar your mom would go to). There were three stations around the edge of the room, each with a wall of cubby holes filled with long, skinny, colorful Nespresso boxes and a few clerks helping select and sell the coffee. There was also a small circular alcove on one side of the room with a well-dressed gentleman in the middle selling coffee and chocolates.

I was pretty overwhelmed — all I wanted was to buy some coffee. Instead of bothering with selecting boxes from one of the walls of coffee, I just picked up a few of the prepackaged collections in the middle of the room. These turned out to be their new flavors and probably cost me twice as much, but at least I didn’t have to communicate.

I got in line to purchase my selection. The line took about five minutes, because the people in front of me each asked for a number of different boxes of coffee and seemed to ask questions about each one. I think the typical shopper walked out of there with about 25 boxes, enough for 250 cups of coffee.

I left there wondering what an equivalent experience in America might be. Something very pedestrian to a resident, but totally far out to a visitor. I haven’t thought of anything yet…