La version française de phTagr, La galerie de photos

July 21st, 2012 Comments off

Since a couple of days the awesome web photo gallery has a French language support. Thanks to François Elie who contributed the French translation – he did a really great work! If your browser prefers the French language and you use the newest version (or on your next update) the web gallery responses in French automatically.

Explorer in French

Is your language missing or incomplete? Please visit the How To Translate Wiki page for further information. There you will find how to create or update a language of the php gallery phtagr.

Categories: announce, user Tags:

New Introduction video on YouTube

July 14th, 2012 Comments off

A short introduction video to phTagr 2.2 was added to YouTube. The video gives some basic introduction to the functionality of phTagr.

Categories: user Tags:

phTagr 2.2 released!

June 29th, 2012 2 comments

I’m thrilled to announce a new stable version of phTagr since 2.1.3 (from January 2011). A lot has changed and plenty improvements found their way on the long road towards an amazing web photo gallery phTagr version 2.2. The new slogan was changed to ‘Tag, Browse, and Share Your Photos’ to clarify the target for your own web base picture album.

The new version 2.2 has an improved tagging workflow and shows
more photos in the explorer. Due multiple access groups per media and a bulk download of files the sharing was simplified, too. 2.2 improves also the current image filter for your custom selection of media.

Visit the demo gallery at

Enjoy using your own private photo gallery phTagr!

Main features since 2.1.3

  • Improved tagging of your media in explorer
  • Bulk download of images as zip archive. Thanks to Damian Popescu
  • Multiple access groups for media for better sharing
  • Add MTS and MP4 file support. Thanks to josefwells
  • Add BMP, PSD, TIF, OGG, and GPX file support
  • Image rotation via explorer
  • Split gallery to frontend and backend
  • Changed frontend theme from greenish to dark
  • Enlarge preview size from 600 to 960 pixels
  • Upgrade CakePHP from 1.3 to 2.1
  • Usage of SASS for easy CSS updates

Other new features

  • Split location search to sublocation, city, state, country
  • Add test cases (66 tests) to avoid regression
  • Add recursive import option. Thanks to Damian Popescu
  • Add read only image filter. This file filter does not write meta data
  • Add new system function: Delete all unused meta data
  • Disable scroll wheel for google Maps
  • Add filter bread crumbs to change current media selection

and of cause endless fixes and improvements

Please read if you like to migrate your older version to 2.2.

Please do not hesitate to download and install phTagr on your LAMP, WAMP, or MAMP. If you want to stay up-to-day, it is recommend to install phTagr via git from GitHub at Fork the project and send pull requests on GitHub for contribution.

Best regards


Categories: announce Tags:

GPS Logger format GPX is now supported

April 6th, 2012 Comments off

phTagr 2.2 is on the way. While fixing and testing the code phTagr added support for GPX tracks. GPX is a great GPS exchange format which is also the export format of Android App OpenGPSTracker. Just record your day trip with OpenGPSTracker and geo tag your photos using a your Android phone! That’s a great news!

There is also now an option in the backend to set the time offset for GPS tracks if your photos are not taken in UTC. This options helps you to synchronize the GPS tracks taken UTC with your local time of your camera.

Happy Easter!

Categories: Nicht kategorisiert Tags: , , , ,

Release 2.1.3

January 14th, 2011 1 comment

I’m proud to announce the release of phtagr version 2.1.3

You can download the new version from sourceforge  at Sourceforge. Read How To Migrate for migration help.

Here are the improvements since 2.1.2

  • Bread Crumb Search The search term is splitted into single search bread crumbs. The search crumbs simplifies the customization of the search
  • Fast preview file responder Now the images are loaded faster and are fast as hell. It by-passes the MVC CakePHP framework stack based on the HTTP session
  • Translations Added Estonian (Craig), Polish (Bartosz Fenski aka fEnIo), Italian (Francesco Piraneo G) translation
  • Mobile Device Support If your are open the gallery with your mobile device a new customized mobile theme is loaded automatically.
  • Email Notification Add email notification for new media which could be triggered by cron job. The notification interval could be set from half an hour to once a month
  • Improved Group Handing The creation and managing of groups is simplified which makes the gallery more social. Try it!
  • SMTP Configuration You can now configure your own SMTP configuration in app/config/core.php to enable email functionality to your web gallery
  • Improved the preview manager. Now a preview might depend on the next larger preview and a preview is not always calculated by the original file which saves a lot of time for smaller previews.
  • Add interval search in the explorer. If you already set a time limit of your search you can easily add another time bound for an interval search.
  • View media based on upload path
  • Add sync shell task to sync all media at once (console based)
  • Add fallback of image size. In rare cases the image size could not extracted correcly. Now getimagesize() should fix this gap.
  • Auto completion for tag, category, and location – also in bread crumbs.
  • And lots of bug fixes…

The next release should get a face lift with a backend and easy customizable frontend – besides tagging, sharing and searching improvements 🙂

Stay tuned!

Categories: announce, info Tags:

Success story: Migration from Zen Photos to phTagr

January 8th, 2011 Comments off

My quest for an open source photo gallery started when my flickr pro account needed renewal, I already had a domain and website, and I thought to myself: “I don’t need to pay flickr, I can do it myself“. So I downloaded all of my flickr photos (about 2 gigs worth) to my local computer and they were organized in directories as they were on flickr. Then I started the search for an open source solution that would be easy to migrate all of my photos to, and what I settled on
was zen photo because I could basically just upload everything with FTP and it would be organized as it was on flickr. It was quick and easy to get setup, however over time what I found was that managing the photos in zen photo was a real pain. The user interface is very cumbersome, and clunky, often times I would make some sort of change only to find later that the change never took because I didn’t scroll waaaay down and hit the “save” button. I also found zenphoto visually
unappealing, even though I could potentially create my own theme, I am not a web designer or an artist so any theme I come up with would be even uglier.

After about a year with zen photo, I decided to start looking around again and that is when I found phtagr, it is a very attractive solution, mass editing and mass  uploads are easy, the user interface is intuitive, and is much more flickr like. The best part is that when I first started using it, I couldn’t get it to work on my webhost, so I e-mailed the phtagr mailing list and Xemle responded quickly and was able to fix my problem. Now it works flawlessly…

Thanks for the hard work.

— by Chris Desjardins

phtagr risponde in italiano

January 3rd, 2011 Comments off

Happy New Year to All!

By today phTagr has now an Italian translation – thanks to Francesco Piraneo G. for his great contribution. The newly updated zip file could be downloaded from SourceForge.

If your language is missing, see How To Translate in the wiki.


Categories: info, user Tags:

Free Online HTML and PHP Editor for CakePHP

December 11th, 2010 Comments off

Baker – The Simple and Free Online Source Editor for CakePHP is published! Baker is a basic online text editor to write text, HTML, or PHP server files online. It’s a CakePHP application and you can do most basic text editor operations.

You can view syntax highlighted source files or edit them. Create, copy, rename, move and delete of files and directories are supported, too. You can upload files and extract ZIP archive. Baker has everything of your need to have a quick change of your PHP or HTML source code.

Baker’s Core Features

  • Syntax highlighting of PHP and HTML files (through Geshi, thanks to Mark for his plugin)
  • Create, Edit, Copy, Rename, Move, Delete files and directories
  • Upload files
  • Extract ZIP archive on server side
  • HTTP User Authentication
  • Filter file list
  • Different virtual directory roots

You can visit the demo page at or download the source from GitHub. Screenshots are available here. See here for installation instructions.

Feel free to use it and to modify it.

Baker was very useful when I developed on phTagr, the free social web gallery, while being in a Internet café far far away with a slow Internet connection. I would love if someone adds SkyWrite Editor (AKA Bespin) to it. For sure Code ‘n Run is more fancy, but it’s not free and coding is fun 🙂

Baker - The Simple and Free Online Source Editor for CakePHP

Directory actions with move, copy, and delete

Syntax Highlighting in the View Mode

Categories: cakephp, info Tags: ,

Improved Preview Handling

October 10th, 2010 1 comment

Recently the preview handling was improved and partly rewritten. The speed boost by the Fast File Responder was previously described here. Before r632 each preview was rendered by the original image which consumed a lot of time. Now an image preview manager was introduced which reuses existing down sampled images to gain speed. While each conversion from the original image costs about 4.4s, the down sampling from an 600px to 220px requires only 0.2s Further each preview configuration (defined in the Preview Manager Component) might be depend on a greater preview image. These dependencies might trigger the generation of all previews before calculating the requested one.

Unfortunately, the preview cache file schema changed and all previews have to be recalculated again. However, since r639 phTagr supports the batch generation of previews with a CakePHP shell script preview. You can create these previews at the command with

$ cd <phtagr base>
$ cakephp/lib/Cake/Console/cake preview generate
Generate preview files
cake preview [subcommand] [options]
generate  Create preview files
To see help on a subcommand use `cake preview [subcommand] --help`
--help, -h         Display this help.
--verbose, -v      Enable verbose output.
--quiet, -q        Enable quiet output.
--max              Maximum generation count. Default is 10. Use 0 to
                   generate all previews
--start-chunk      Set the start chunk number. A chunk has a size of 100
                   media. Default is 1
--size             Set the minimum preview size. Default is thumb
                   (choices: mini|thumb|preview|high)
--user             Generate only previews for given user
$ cakephp/lib/Cake/Console/cake preview generate --size mini -v
Page 1/180 (0.56%)
Page 2/180 (1.11%)
Page 3/180 (1.67%)

Update 2012-07-22: Updated commands to version 2.2-dev.

Categories: tools, user Tags: ,

Fast File Responder for CakePHP

October 3rd, 2010 1 comment

This article is very useful for all CakePHP applications which deal with lots of photos or other files which are shown in the resulting page. I will introduce an Fast File Responder for CakePHP which immediately sends the file to the client without stepping into the CakePHP stack. It increases the performances drastically to an minimum and got its inspiration from Lightning Fast Caching for CakePHP. The provided approach of the Fast File Responder is used in the open source social web gallery phTagr.

The web gallery phTagr is written on top of the great MVC framework CakePHP and deals with lots of photos. Its photo explorer displays by default 12 photos at once (see demo page). Therefore the CakePHP framework is called 13 times. The first request handles the authorized and the selection of the 12 photos. Then each photo is requested by the client to fetch it and to display it into the page. These requests check again the authorization and correctness of the user for each photo and requires a lot of time since it traverses again the whole MVC stack.

time = 1 x explorer page + 12 x image request = 13 x CakePHP stack = 13 x ~0.40s = 3,40s

Since the first request already checked the authorization of the photos the following 12 requests and checks are redundant and can be omitted. The user session can be used to store these authorization information for the 12 media requests and the photos could be send immediately before the CakePHP stack is called.

time = 1 x explorer page + 12 x fast image request = 1 x CakePHP stack = 0.45s

To do so a Fast File Responder component adds the file information to the session. It adds for each photo request the filename of the preview and an expiration date for safety.

class FastFileResponderComponent extens Object {
  var $controller = null;
  var $components = array('Session', 'FileCache');
  var $sessionKey = 'fastFile.items';
  var $expireOffset = 10; // seconds
  function initialize(&$controller) {
    $this->controller = $controller;
  function add($key, $filename) {
    if (!is_readable($filename)) {
      return false;
    $files = (array) $this->Session->read($this->sessionKey);
    $files[$key] = array('expires' => time() + $this->expireOffset, 'file' => $filename);
    $this->Session->write($this->sessionKey, $files);
    return true;
  function addAll($data) {
    foreach ($data as $key => $filename) {
      $this->add($key, $filename);

Than the app/webroot/index.php is modified to check for fast files before the MVC stack is called.

  // ...
  if (!defined('CORE_PATH')) {
    // ...
  // Check the request URI if it matches the URI for photos
  if (isset($_GET['url']) && preg_match('/media\/\w+\/\d+/', $_GET['url'])) {
    require ROOT . DS . APP_DIR . DS . 'fast_file_responder.php';
    $fileResponder = new FastFileResponder();
    if ($fileResponder->exists()) {
    } else {
  if (!include(CORE_PATH . 'cake' . DS . 'bootstrap.php')) {
    // ...
  // ...

Finally the Fast File Responder itself located in app/fast_file_responder.php

/** This class enables a fast file response without the framework stack of
 * CakePHP. It checks the session and the URL and returns a valid file */
class FastFileResponder {
  /** Should be same as in app/config/core.php Session.cookie */
  var $sessionCookie = 'CAKEPHP';
  var $sessionKey = 'fastFile';
  var $items = array();
  function __construct() {
  /** Starts the session if the session sessionCookie is set */
  function startSession() {
    if (!isset($_COOKIE[$this->sessionCookie])) {
    if (isset($_SESSION[$this->sessionKey])) {
      $this->items = (array) $_SESSION[$this->sessionKey]['items'];
  /** Deletes expired itemes from the session list */
  function deleteExpiredItems() {
    if (!count($this->items)) {
    $now = time();
    foreach ($this->items as $key => $item) {
      if ($item['expires'] < $now) {
  /** Simple log function for debug purpos */
  function log($msg) {
    $h = @fopen(dirname(__FILE__) . DS . 'fast_file_responder.log', 'a');
    @fwrite($h, sprintf("%s %s\n", date('Y-M-d h:i:s', time()), $msg));
  /** Extracts the item key from the url and returns it. Returns false if no
   * key could be found. This function must be adapted for others */
  function getItemKey() {
    if (!isset($_GET['url'])) {
      return false;
    $url = $_GET['url'];
    if (!preg_match('/media\/(\w+)\/(\d+)/', $url, $matches)) {
      return false;
    return $matches[1] . '-' . $matches[2];
  /** Returns the file of the media request */
  function getFilename() {
    $key = $this->getItemKey();
    if (!$key || !isset($this->items[$key])) {
      return false;
    $item = $this->items[$key];
    if ($item['expires'] < time() || !is_readable($item['file'])) {
      return false;
    return $item['file'];
  /** Returns an array of request headers */
  function getRequestHeaders() {
    $headers = array();
    if (function_exists('apache_request_headers')) {
      $headers = apache_request_headers();
      foreach($headers as $h => $v) {
        $headers[strtolower($h)] = $v;
    } else {
      $headers = array();
      foreach($_SERVER as $h => $v) {
        if(ereg('HTTP_(.+)', $h, $hp)) {
          $headers[strtolower($hp[1])] = $v;
    return $headers;
  /** Evaluates the client file cache and response if the client has still a
   * valid file
   * @param filename Current cache file */
  function checkClientCache($filename) {
    $cacheTime = filemtime($filename);
    $headers = $this->getRequestHeaders();
    if (isset($headers['if-modified-since']) &&
        (strtotime($headers['if-modified-since']) == $cacheTime)) {
      header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $cacheTime).' GMT', true, 304);
      // Allow further caching for 30 days
      header('Cache-Control: max-age=2592000, must-revalidate');
  function sendResponseHeaders($file) {
    $fileSize = @filesize($file);
    header('Content-Type: image/jpg');
    header('Content-Length: ' . $fileSize);
    header('Cache-Control: max-age=2592000, must-revalidate');
    header('Pragma: cache');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($file)));
  /** Evaluates if a valid cache file exists */
  function exists() {
    return $this->getFilename() != false;
  /** Sends the cache file if it exists and exit. If it returns an error
    * occured */
  function send() {
    $filename = $this->getFilename();
    if (!$filename) {
      return false;
    $chunkSize = 1024;
    $buffer = '';
    $handle = fopen($filename, 'rb');
    while (!feof($handle)) {
      $buffer = fread($handle, $chunkSize);
      echo $buffer;
    //$this->log("File send: $filename");
  /** Closes the session */
  function close() {

Now the requested images are shown almost simultaneously with the explorer photo page. Awesome!

Please leave a comment if you liked this proposal.

Categories: cakephp Tags: