OTFG Step 11: Displaying and Editing Photos

Good morning, off the grid fans! I know it's been a while—I've been working on my new photoblog behind the scenes. I'm at a point where I'm not sure it helps anyone to share my code, but who knows? Last time I talked about how I'm getting photos into my system, and today I'll explain how I'm editing photos that are already in the system.
Photo URLs
The first thing I needed to do was provide a permanent home for every photo that finds its way into my database. The easiest method would be using the internal photo ID in the URL somehow, so I'd end up with a URL for any photo like http://photos.onfocus.com/459918/. But as I mentioned when designing the photo file locations (Thinking about Photo URLs), I want to include a bit more information about the photo in the URL. So I went with a pattern similar to the files: http://photos.onfocus.com/[year]/[month]/[title]. As with files, the title is stripped of any non-URL-approved characters, and whitespace is replaced with a dash.

I also wanted to keep photo IDs internal, and not use them anywhere within the public-facing application. So I thought the URL pattern of [year]/[month]/[title] would be a good way to uniquely identify a photo within the system as long as there were no duplicates. To make this happen I set up a field in the database called Stub (varchar(50)) that holds the entire string: [year]/[month]/[title]. If two photos have the same title within the same year and month, I simply increment the stub like this: [year]/[month]/[title]-1, [year]/[month]/[title]-2, etc. This way the permalink can be used not only to see the photo on the Web, but also to identify the photo within the application.

I wrote a quick script to add URL stubs to all of the existing photos: addStubs.php. And I retrofitted all of the uploading scripts from the last step to write a URL stub as a photo is added.

With the virtual space for photos set to go, I needed to give them a permanent home. I set up a script called photo.php that shows one photo at a time, along with a bunch of details about that photo. By passing a URL stub into the script like this http://photos.onfocus.com/photo.php?p=[photo stub], the page knows which photo to display. With a little .htaccess magic: RewriteRule ^(\d{4}/\d{2}/.*)$ photo.php?p=$1 [L] the nicely formatted URLs are a reality: for example, bandon beach.
Photo Detail Page
So the photo detail page accepts an incoming URL stub, looks up info about that photo in the database, and arranges things nicely on the page. Here's what a photo detail page looks like in my system today:

otfg photo detail

The main bits are the title, photo itself, caption, time the photo was posted, and a list of tags associated with the photo. This is the public view. If you have the right credentials (set up in Step 9: Authentication), you see a bit more on the page, and you have a few more options. As an administrator, directly below the caption is a row of administrative buttons:

otfg admin buttons

Here's what each button does:
  • Sets the public/private status of the photo.
  • Toggles the caption editing form.
  • Rotates the photo 90 degrees clockwise.
  • Completely removes the photo, its thumbnails, and all associated info.
The other thing an admin can do is edit the title, caption, and tags in place by clicking on any of these things (like Flickr). It looks like this:

otfg editing title

All of this editing is accomplished with a series of files. The Ajax package Prototype handles some of the work in the background. And the rest of the interface stuff is in a Javascript file that's included on the page for an administrator: editing.js. The functions in this file post to several PHP scripts that return simple text information: The only function that requires a page refresh is completely deleting a photo, which is ok with me because the photo detail page is about to be history anyway and I've got to go somewhere. The administrative buttons all have a JavaScript confirmation dialog before they execute, so I can't accidentally delete a photo when I want to rotate it.

And here's the beast of a script that pulls everything together: photo.php. This is fairly complex, especially because the public design and administrative functions live together in the same page.
Photo Home Page
With the photo detail page set, I set up a place to introduce people to my photos: the home page. Again, it's very Flickrish, with two columns of photos and a list of pages at the bottom. The only difference is that the latest photo is at its largest size at the top. I haven't built any editing into this page yet, so any updates have to happen on photo detail pages. And here's the code that powers the front page: home.php. I set up an .htaccess rule for this page too, to help with paging: ^home/(\d{1,2})/?$ home.php?page=$1 [L]. That way, as you page through the photos, you'll get friendly URLs like this: http://photos.onfocus.com/home/2.

I think this step gives me a functioning system I can use to publish photos. There are definitely more features I need to build: browsing by tag, extracting EXIF data, an RSS feed, galleries/sets, commenting, and mapping photos with coordinates. And I have some issues I need to work out. (Anyone know how to force a cache refresh on photos after rotation beyond adding some random numbers to the file name?) But I think all of the bare essentials for sharing photos with the world are working now. woohoo! You can compare my local photostream to my Flickr photostream to see how similar they are.

By the way, the little administrative and tag icons are all modified from a set of tiny icons by Timothy Groves: Ho!Ho!Ho!. Thanks!