Home Contact Buy
Sitemap Contact
Home Download Video Free Buy Sitemap Contact

Information for Developers


Anuko Time Tracker was initially created out of a basic need to track work time on a project for a small team. We needed something simple, quickly, and this is how it all started.

The approach worked reasonably well. However, over time the system evolved. The initial simple design did not address flexibility and extensibility issues that many users require. For example, Time Tracker was not designed initially for plugins. As a results, existing plugins are not "real" plugins one might expect. They are more like optional "features" that a user can turn on or off. A redesign and some serious refactoring are both needed to do this right. You are welcome to suggest improvement ideas.

Web Application

Time Tracker is a web application written in PHP. Supported versions of PHP - 5.4 - 7.x. If something does not work or does not work well please let us know and we'll either fix the problem or document it here.

See dbinstall.php for problems with earlier versions of PHP:
// Check if PHP version is good enough.
// $required_version = '5.2.1'; // Something in TCPDF library does not work below this one.
$required_version = '5.4.0';    // Week view (week.php) requires 5.4 because of []-way of referencing arrays.
                                // This needs further investigation as we use [] elsewhere without obvious problems.


Time Tracker uses MariaDB or MySQL as a database. We use PEAR MDB2 package to access the database. Connection parameters are defined in the DSN value in config.php. Theoretically, PEAR MDB2 should provide some isolation from the database engine. Practically, other database engines have not been tried. We expect some issues with other databases. You are welcome to identify these issues to see if the code can be adjusted.


Time Tracker uses Smarty template engine for presentation, which is included in Time Tracker download in WEB-INF/lib/smarty directory.

Presentation of a PHP page is accomplished by coupling a .php file with a .tpl file. For example, in the end of time.php we have this:
$smarty->assign('content_page_name', 'time.tpl');
Which means use time.tpl from the templates directory, and then display everything using index.tpl. Therefore, for each PHP page we show to users, we have a corresponding template file, usually named similarly. Pages for mobile access are organized the same way in mobile subdirectories.

User Object

A logged on user to the system is represented by a single instance of ttUser class. It is initialized in initialize.php and is referenced in PHP files, in Smarty templates, and in class functions as:

For class functions to see the instance, we declare it as so in the beginning of the function.
global $user;

User instance has many properties, see WEB-INF/lib/ttUser.class.php. For example:
class ttUser {
  var $login = null;            // User login.
  var $name = null;             // User name.
  var $id = null;               // User id.
  var $team_id = null;          // Team id.
  var $role = null;             // User role (user, client, comanager, manager, admin).
  var $client_id = null;        // Client id for client user role.
  var $behalf_id = null;        // User id, on behalf of whom we are working.
  var $behalf_name = null;      // User name, on behalf of whom we are working.
  var $email = null;            // User email.
  var $lang = null;             // Language.
  var $decimal_mark = null;     // Decimal separator.
  var $date_format = null;      // Date format.
  var $time_format = null;      // Time format.
  var $week_start = 0;          // Week start day.
  var $tracking_mode = 0;       // Tracking mode.
  var $project_required = 0;    // Whether project selection is required on time entires.
  var $task_required = 0;       // Whether task selection is required on time entires.
  var $record_type = 0;         // Record type (duration vs start and finish, or both).
  var $uncompleted_indicators = 0; // Uncompleted time entry indicators (show nowhere or on users page).
  var $bcc_email = null;        // Bcc email.
  var $currency = null;         // Currency.
  var $plugins = null;          // Comma-separated list of enabled plugins.
  var $team = null;             // Team name.
  var $custom_logo = 0;         // Whether to use a custom logo for team.
  var $address = null;          // Address for invoices.
  var $lock_spec = null;        // Cron specification for record locking.
  var $workday_hours = 8;       // Number of work hours in a regular day.
  var $rights = 0;              // A mask of user rights.
These properties are initialized when the instance is created in initialize.php. As a programmer, you have access to $user instance from everywhere else in the code.

Internationalization Object

Time Tracker uses I18n class (see WEB-INF/lib/I18n.class.php) for strings localized in user language. As $user, it is constructed in initialize.php after we determine user language, and then becomes available to the rest of the application as:
or, inside of functions, where needed:
global $i18n;
Translation strings are loaded from files in WEB-INF/resources/ - one file per language. Some files are only partially translated. Feel free to improve the translation for your language.

Execution Flow

As a web application, Time Tracker consists of a set of .php pages, where users do their things. For example, time.php is used for daily time entry. This file is not the simplest to analyze, but let's be brave and try to look at some code fragments.

In the beginning, we require initialize.php, which initializes global $user and $i18n objects, among other things.
Then we do access checks.
// Access checks.
if (!(ttAccessAllowed('track_own_time') || ttAccessAllowed('track_time'))) {
  header('Location: access_denied.php');
The ttAccessAllowed call above redirects to login.php if a visitor is not logged in.

The remainder of the file prepares variables for display. Then, in case of HTTP GET we pass control to the template for display, or, in case of HTTP POST, we handle the post.

Most other files work in a similar way.

Some files are much simpler and don't have a POST handler. Look at tasks.php and projects.php, which display tasks and projects available to user.

Directory Structure

Here is how Time Tracker directory structure looks like and what is inside.
/ - PHP pages for desktop browsers.
/WEB-INF/config.php - Time Tracker configuration file.
/WEB-INF/config.php.dist - distribution example of the config.php file with default settings.
/WEB-INF/lib/ - library directory containing helper classes, PEAR, Smarty, and other packages and modules.
/WEB-INF/resources/ - translation files, one per language.
/WEB-INF/templates/ - Smarty templates for desktop pages.
/WEB-INF/templates/mobile/ - Smarty templates for mobile pages.
/WEB-INF/templates_c/ - directory where Smarty stores compiled templates. It must be writable.
/img/ - graphic files.
/js/ - JavaScript files.
/mobile - PHP pages for mobile browsers.
/plugins/ - plugins directory.
To understand basic execution flow, pay attention only to these four:
/ - PHP pages for desktop browsers.
/mobile - PHP pages for mobile browsers.
/WEB-INF/templates/ - Smarty templates for desktop pages.
/WEB-INF/templates/mobile/ - Smarty templates for mobile pages.
Everything else is secondary and is used to create output for each PHP-template pair.

Suppose we want to create a new feature in Time Tracker as a separate PHP page. We will need to create a .php page and a corresponding .tpl page. If we want this page on mobile devices, we will also need another mobile pair (total 4 files).


See the History section on top. Currently, there is no documented interface for plugins, although we do have /plugins/ directory, where new plugin classes are supposed to go.

Moving forward, we would like to have plugins designed and implemented properly, with hopefully a clean interface. If you are thinking about a new plugin feel free to suggest a better approach, which works for your plugin as well as others'.

Current plugins work as follows.

Plugins are turned on or off on the team profile page. Each plugin is identified by a 2-character designation, for example:
ch - charts.
cl - clients.
iv - invoices.
When $user instance is initialized, it obtains a list of enabled plugins into its $plugins member, which is a comma-separated list of plugin designations. You can determine whether a plugin is enabled by calling the ttUser::isPluginEnabled() function with a plugin designation parameter:
// isPluginEnabled checks whether a plugin is enabled for user.
function isPluginEnabled($plugin)
  return in_array($plugin, explode(',', $this->plugins));
Then, on presentation PHP pages, we invoke plugin code depending on whether or not it is enabled for user, and conditionally include plugin presentation parts in corresponding Smarty templates.

A plugin may have to introduce changes to the database structure. Our existing approach, which may (has to?) be changed, is one structure for everything, and one localization file for all strings.

Documenting in Progress

This is work in progress. If you are a developer looking for additional information please let us know what should be covered here. Use the Contact form or by a post on the forum.