FOSS Fridays: MacGyvered Key/Value in Symfony

On a project we’re currently working on, we arrived at a situation where our client had a loose and very fluid idea of the information he wanted to store about certain objects in his application. We didn’t specifically know the number of fields or the format of the data. Continually modifying the schema would of been painful so I wanted to try something different.

Since the data is more or less non-relational (it only relates to the object that owns it), what I really wanted was an ad-hoc key/value store. But I didn’t want to break Propel’s ORM abstractions. I still wanted to be able to do:

$company->getMission();

With the new system.

Turns out you basically can. Here’s how it works:

  1. Add a “dynamic_field” table to your schema. (definition is below)
  2. Override the __call(), hydrate(), and save() functions in Propel model file that you want to MacGyver.
  3. Pray.

Definition of the dynamic_field table:

So the idea is we want to basically build a Propel Behaviour to capture any undefined get/set calls and “get” the data out of the dynamic_field table or “set” the data by storing the value into the table. Since the table stores the model class and model id, the “keys” only have to be unique by model (just like Propel normally works).

Here is the code you need to add to the model file:

The code captures any undefined get/set calls and then deals with them appropriately. It won’t serialize the fields until the save() call (just like regular Propel objects). I also overloaded the hydrate() function so that the object will fetch all of its dynamic fields in one shot, as opposed one query per get.

Using the modified objects is exactly like regular Propel objects, the changes are entirely transparent except that you can get/set anything you want.

For example:

Will work even though there is no “vision” column on the company table. Magic.

There is one big problem with this trick though. Because of the Propel class hierarchy, there isn’t any way to introduce this code in one file and have other objects inherit the changes. You have to manually copy it to any model file that you want to enable it for.

Google Calender embed missing events

So we decided to use the Google Calendar API in one of our applications to allow users to easily view and export events from outside the app. In general, the API was working well – I was using the Zend library to interact with Google and things seemed fine.

That was until I tried to embed the calendar using Google’s iframe embed code. For some reason, events weren’t showing up in the embeded iframe calendar even though they were showing up in the actual calendar on calendar.google.com. Even stranger, the events were present in a JSON object on the embeded page and they were showing up in the RSS feed for the calendar.

After literally days of debugging and experimenting I finally found out the culprit.

For some reason, events created via the API that start and end at exactly the same time – say a start date of 08-05-2009 10:00:00 and an end date of 08-05-2009 10:00:00 don’t render on the embeded iframe calendar.

What is even more bizarre is that if you create an event via the web interface that starts and ends at the same time, it will render correctly on an embeded calendar.

Anyway, that was weird. All the events without explicit start and end times now last a grand total of one minute.

PS. Kudos to Daum for finding a constant for PHP’s date() function to generate RFC3339 timestamps.

Use like so:

  $date = date(DATE_RFC3339, $timestamp);

To get back a valid RFC3339 for the Google Calendar API.

FOSS Fridays: OpenSSL in PHP

Well Twitter has “Follow Fridays” so I thought we should do FOSS Fridays. I don’t really have a plan for this and it might not last but let’s see where it goes.

In the last few days a couple of people have asked for tips on how to use OpenSSL from PHP. So here is a snippet on how to do it. This comes out of an application that provides a shared authentication system between our client’s LDAP system and their partner’s systems.

It works like so:

  1. Users login to the application using their LDAP credentials.
  2. When the users request to visit the partner site, our system packages up their login information, encrypts it, signs it, and shoots it along with the user to the partner site.
  3. Next, the partner checks if the user has an account and if they do it logs them in. Otherwise, it creates them a new account and logs them in.

All of this is done transparently so that the user doesn’t know they’ve actually left the original site.

Here is the code to do it. PS. it’s from a Symfony application.

The net result of all of this is an encrypted payload with the user’s credentials and a signature of the payload. The payload is encrypted with “their” public key and then signed with “our” private key. This ensures that only they can open the package and only we can generate valid signatures.

Happy Friday!

Google Calendar API create on alternate calendar

A few months ago we integrated Google calendar into an application that we built for a client. Anyway, today I sat down to customize which calendars certain events were being created on. We’re using the Zend Framework’s GData package to interact with Google Calendar and surprisingly the documentation is pretty lacking.

Specifically, I was looking to create events on a calendar that was not the “primary” calendar for a user. After poking around and experimenting, I finally got things to work.

First, you can retrieve the list of available calendars with:

Next, when creating the events pass in the uri and the events will appear on the alternate calendar.

self::$service->insertEvent($event, $arr[1][“uri”]);

99designs and Amazon. Design. Crowd sourced.

A week or so ago my Dad asked if we could have our designer put together a logo for him. Unfortunately, our guy was buried under a mound of work and generally couldn’t help us out. We haven’t always had the best luck with Craigslist so I was ready to try something new.

Over the last few months, I’ve been seeing a good amount of chatter surrounding “spec” design sites especially 99designs.com. After taking a look around the site I figured now was a good time to give it a shot. We were on a tight budget, tight time line, and my Dad didn’t have much direction for the logo.

I posted up a contest last Sunday here and we were looking at entries by Monday afternoon. Now things got more difficult. We were having a hard time coming up with “star ratings” and constructive feedback in general. My Dad’s staff was having a hard time not getting pigeon holed by the submitted designs and Setfive wasn’t doing a great job helping them along.

We did our best and we felt like the entries were moving in the right direction. Then the contest closed. In the last 8 hours of the contest the number of entries nearly doubled. With 70 entries we now had the problem with objectively picking a winning logo.

At this point, I wanted some more input on what people thought about the logos. I decided to create a set of Amazon Mechanical Turk tasks to get some feedback.

After about a day, I had 200 responses asking for user’s top three logos and any additional comments they had.

Some of the comments I got back were insightful and moving:

  • Don’t pick any of the logos on the second page. They all look terrible.
  • Due to nature of your business I would prefer a sober and serious looking logo.
  • I chose these three because they are visually appealing, and convey a sense of being able to ease pain.
  • I suffer from cronic pain. I wish you the best of luck in finding your logo. People that do your type of work are a life line for people like me. Hope I hope have helped.

I tallied up the results by weighting +3, +2, +1 for first, second, and third choices respectively. The results were interesting.

  • Every logo received at least one vote.
  • The top ten logos accounted for just about 41% of all the votes.
  • Only counting the top choice caused 3 logos to fall out of the top ten.

The top ten logos as voted by the Amazon Mechanical Turks were:

Entry ID Votes URL

88

76

http://99designs.com/contests/24619/entries/88

78

65

http://99designs.com/contests/24619/entries/78

75

60

http://99designs.com/contests/24619/entries/75

87

55

http://99designs.com/contests/24619/entries/87

91

51

http://99designs.com/contests/24619/entries/91

58

48

http://99designs.com/contests/24619/entries/58

47

42

http://99designs.com/contests/24619/entries/47

90

41

http://99designs.com/contests/24619/entries/90

43

36

http://99designs.com/contests/24619/entries/43

Personally, I like the top ten logos and my Dad’s staff seems to like many of the same logos that were voted up. It’s been an interesting experiment almost exclusively using the “crowd” to design and then select a logo. I’m not sure if we’ll use 99designs in the future but it has been a pleasant experience.

We still haven’t picked a winning logo but I’ll update once we do!

Update:

We finally picked a winner! We decided to go with the crowd and selected http://99designs.com/contests/24619/entries/88 as the winning logo.