Archive for the ‘Related Links’ Category

Debug phtagr with Netbeans 7.2

September 17th, 2012 Comments off

Following instructions gives you a small HowTo for debugging phTagr code with Netbeans 7.2 and Xdebug on Ubuntu 12.04.

If you like to contribute some code to the phtagr project it is recommended to use a IDE with debugging support. Netbeans IDE is a great and free IDE with a good PHP language support. Combined with the PHP debugger and profiler Xdebug you can execute your code line by line and inspect variables which makes changes and errors easy to handle.

Requirements – Assumptions

  • You have some (php) programming skills
  • You installed and configured phtagr on your local web server like apache
  • You use phtagr source from  phtagr’s git repository

Install Netbeans and Xdebug

  • Download Netbeans 7.2 for PHP from

    $ chmod 755
    $ ./

    and follow the installation wizard (windows like). For detailed installation instruction visit netbeans.

  • Install xdebug via sudo apt-get install php5-xdebug. By default xdebug has a configuration file at /etc/php5/conf.d/xdebug.ini.

Create project

  • Start netbeans (e.g. run /home/sebastian/netbeans-7.2/bin/netbeans if you installed netbeans in /home/sebastian/netbeans-7.2).
  • Create a new project via menu File -> New Project
  • Select PHP Application with existing Source. Confirm by clicking Next
  • Enter your php git repository (e.g. /var/www/tests/phtagr), the project name. Confirm by clicking Next
  • Enter the Project URL. At my machine /var/www is Apache’s web root so http://localhost/tests/phtagr is the correct Project URL. At Index File enter webroot/index.php. Netbeans requires a real file and the main index file of phtagr is in webroot/index.php. Confirm by clicking Next
  • Ensure at Menu Tools -> Options -> PHP -> Debugging that Stop at First line is disabled.

Debug phtagr

  • Run Debug Project (shortcut Ctrl+F5). At the first page phtagr will report an error. But this is necessary to set the correct debug cookie for xdebug. Now you can use your phtagr installation and enter Project URL http://localhost/tests/phtagr.
  • Use breakpoints to intercept the execution of php script. E.g. set a break point at Controller/AppController.php to function beforeFilter function but clicking on a line number. If you reload the page in your browser by hitting F5, netbeans will stop at your breakpoint line.


  • Ctrl+F5 – Start debugger
  • F8 – Step Over
  • F7 – Step Into
  • Ctrl+F7 – Step Out
  • F5 – Continue
Categories: source Tags: , ,

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 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:

Improved Groups and Email Notifications

September 4th, 2010 1 comment

Today I published two significant improvements of this great gallery which boosts the user experience and the social interaction.

Until now the powerful access control of your media was just fun for you – but now it is easier than ever to share your photos in groups with your friends. A group got a new description text and some flag for the management. Other users can now see your groups and can subscribe the them by just a single click. It depends on you if your friends are able join the group immediately or the new subscriber needs a confirmation. Further a group can be shared, too. Other group members can assign a shared group to their media as well and all group members are able to see these photos or videos.

The other great feature is a shell task which sends notification emails of new media for users. It should be uses in a cron job and will inform your uses of your gallery on new uploads. Since your shell has no clue about your gallery URL, you have to configure it in the core.php with the parameter Notification.url. To test is you can use one of the parameters verbose, dryrun, noemail, or force.

8 15 * * * /var/www/phtagr/cake/console/cake -app /var/www/phtagr/app notify run

Please run the setup to upgrade your database (and do not forget to make a backup before – just in case).

Categories: announce, Related Links, user Tags: ,

phTagr z językiem polskim

September 3rd, 2010 2 comments

I’m pleased to announce that phTagr has now an Polish translation – many thanks to Bartosz Fenski (aka fEnIo) for his time. The fresh baked zip file could be downloaded from SourceForge.

Categories: user Tags:

phTagr räägib nüüd eesti keeles

August 13th, 2010 Comments off

I’m happy to announce that phTagr has now an Estonian translation. Thanks to Craig for his great work who found also lots of missing translation texts. The fresh baked zip file could be downloaded from SourceForge. For upgrade information please have a look at our wiki page.

Further, phTagr supports now the media selection by the upload folder. This feature is very useful for albums which are ordered by folder. The folder link could be found by media detail tab in the media view.

Categories: user Tags: