A bit more refactoring.
[timetracker.git] / initialize.php
1 <?php
2 // +----------------------------------------------------------------------+
3 // | Anuko Time Tracker
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) Anuko International Ltd. (https://www.anuko.com)
6 // +----------------------------------------------------------------------+
7 // | LIBERAL FREEWARE LICENSE: This source code document may be used
8 // | by anyone for any purpose, and freely redistributed alone or in
9 // | combination with other software, provided that the license is obeyed.
10 // |
11 // | There are only two ways to violate the license:
12 // |
13 // | 1. To redistribute this code in source form, with the copyright
14 // |    notice or license removed or altered. (Distributing in compiled
15 // |    forms without embedded copyright notices is permitted).
16 // |
17 // | 2. To redistribute modified versions of this code in *any* form
18 // |    that bears insufficient indications that the modifications are
19 // |    not the work of the original author(s).
20 // |
21 // | This license applies to this document only, not any other software
22 // | that it may be combined with.
23 // |
24 // +----------------------------------------------------------------------+
25 // | Contributors:
26 // | https://www.anuko.com/time_tracker/credits.htm
27 // +----------------------------------------------------------------------+
28
29 // Report all errors except E_NOTICE and E_STRICT.
30 // Ignoring E_STRICT is here because PEAR 1.9.4 that we use is not E_STRICT compliant.
31 if (!defined('E_STRICT')) define('E_STRICT', 2048);
32 // if (!defined('E_DEPRECATED')) define('E_DEPRECATED', 8192);
33 error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT); // & ~E_DEPRECATED);
34 // E_ALL tends to change as PHP evloves, therefore we use & here instead of exclusive OR (^).
35
36 // Disable displaying errors on screen.
37 ini_set('display_errors', 'Off');
38
39 // require_once('init_auth.php');
40 define("APP_DIR", dirname(__FILE__));
41 define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib");
42 define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates");
43 // Date format for database and URI parameters.
44 define('DB_DATEFORMAT', '%Y-%m-%d');
45
46 require_once(LIBRARY_DIR.'/common.lib.php');
47
48 // Require the configuration file with application settings.
49 if (!file_exists(APP_DIR."/WEB-INF/config.php")) die ("WEB-INF/config.php file does not exist.");
50 require_once("WEB-INF/config.php");
51 // Check whether DSN is defined.
52 if (!defined("DSN")) {
53   die ("DSN value is not defined. Check your config.php file.");
54 }
55
56 // Depending on DSN, require either mysqli or mysql extensions.
57 if (strrpos(DSN, 'mysqli://', -strlen(DSN)) !== FALSE) {
58   check_extension('mysqli'); // DSN starts with mysqli:// - require mysqli extension.
59 }
60 if (strrpos(DSN, 'mysql://', -strlen(DSN)) !== FALSE) {
61   check_extension('mysql');  // DSN starts with mysql:// - require mysql extension.
62 }
63
64 // Require other extensions.
65 check_extension('mbstring');
66
67 // If auth params are not defined (in config.php) - initialize with an empty array.
68 if (!isset($GLOBALS['AUTH_MODULE_PARAMS']) || !is_array($GLOBALS['AUTH_MODULE_PARAMS']))
69   $GLOBALS['AUTH_MODULE_PARAMS'] = array();
70
71 // Smarty initialization.
72 import('smarty.Smarty');
73 $smarty = new Smarty;
74 $smarty->use_sub_dirs = false;
75 $smarty->template_dir = TEMPLATE_DIR;
76 $smarty->compile_dir  = TEMPLATE_DIR.'_c';
77
78 // Note: these 3 settings below used to be in .htaccess file. Moved them here to eliminate "error 500" problems
79 // with some shared hostings that do not have AllowOverride Options or AllowOverride All in their apache configurations.
80 // Change http cache expiration time to 1 minute.
81 session_cache_expire(1);
82
83 $phpsessid_ttl = defined('PHPSESSID_TTL') ? PHPSESSID_TTL : 60*60*24;
84 // Set lifetime for garbage collection.
85 ini_set('session.gc_maxlifetime', $phpsessid_ttl);
86 // Set PHP session path, if defined to avoid garbage collection interference from other scripts.
87 if (defined('PHP_SESSION_PATH')) {
88   ini_set('session.save_path', PHP_SESSION_PATH);
89   ini_set('session.gc_probability', 1);
90 }
91
92 // Set session cookie lifetime.
93 session_set_cookie_params($phpsessid_ttl);
94 if (isset($_COOKIE['tt_PHPSESSID'])) {
95   // Extend PHP session cookie lifetime by PHPSESSID_TTL (if defined, otherwise 24 hours) 
96   // so that users don't have to re-login during this period from now. 
97   setcookie('tt_PHPSESSID', $_COOKIE['tt_PHPSESSID'],  time() + $phpsessid_ttl, '/');
98 }
99
100 // Start or resume PHP session.
101 session_name('tt_PHPSESSID'); // "tt_" prefix is to avoid sharing session with other PHP apps that do not name session.
102 @session_start();
103
104 // Authorization.
105 import('Auth');
106 $auth = Auth::factory(AUTH_MODULE, $GLOBALS['AUTH_MODULE_PARAMS']);
107
108 // Some defines we'll need.
109 //
110 define('RESOURCE_DIR', APP_DIR.'/WEB-INF/resources');
111 define('COOKIE_EXPIRE', 60*60*24*30); // Cookies expire in 30 days.
112
113 // Status values for projects, users, etc.
114 define('ACTIVE', 1);
115 define('INACTIVE', 0);
116 // define('DELETED', -1); // DELETED items should have a NULL status. This allows us to have duplicate NULL status entries with existing indexes.
117
118 // Definitions for tracking mode types.
119 define('MODE_TIME', 0); // Tracking time only. There are no projects or tasks.
120 define('MODE_PROJECTS', 1); // Tracking time per projects. There are no tasks.
121 define('MODE_PROJECTS_AND_TASKS', 2); // Tracking time for projects and tasks.
122
123 // Definitions of types for time records.
124 define('TYPE_ALL', 0); // Time record can be specified with either duration or start and finish times.
125 define('TYPE_START_FINISH', 1); // Time record has start and finish times.
126 define('TYPE_DURATION', 2); // Time record has only duration, no start and finish times.
127
128 // Definitions for uncompleted time entry indicators.
129 define('UNCOMPLETED_INDICATORS_NONE', 0); // Do not show indicators.
130 define('UNCOMPLETED_INDICATORS', 1); // Show indicators.
131
132 // User access rights - bits that collectively define an access mask to the system (a role).
133 // We'll have some bits here (1,2, etc...) reserved for future use.
134 define('right_data_entry', 4);     // Right to enter work hours and expenses.
135 define('right_view_charts', 8);    // Right to view charts.
136 define('right_view_reports', 16);  // Right to view reports.
137 define('right_view_invoices', 32); // Right to view invoices.
138 define('right_manage_team', 64);   // Right to manage team. Note that this is not full access to team.
139 define('right_assign_roles', 128); // Right to assign user roles.
140 define('right_export_team', 256);  // Right to export team data to a file.
141 define('right_administer_site', 1024); // Admin account right to manage the application as a whole. 
142
143 // User roles.
144 define('ROLE_USER', 4);          // Regular user.
145 define('ROLE_CLIENT', 16);       // Client (to view reports and invoices).
146 define('ROLE_COMANAGER', 68);    // Team co-manager. Can do many things but not as much as team manager.
147 define('ROLE_MANAGER', 324);     // Team manager. Can do everything for a team.
148 define('ROLE_SITE_ADMIN', 1024); // Site administrator.
149
150
151 define('CHARSET', 'utf-8');
152
153 date_default_timezone_set(@date_default_timezone_get());
154
155 // Strip auto-inserted extra slashes when magic_quotes ON for PHP versions prior to 5.4.0.
156 if (get_magic_quotes_gpc())
157   magic_quotes_off();
158
159 // Initialize global objects that are needed for the application.
160 import('html.HttpRequest');
161 $request = new ttHttpRequest();
162
163 import('form.ActionErrors');
164 $err = new ActionErrors(); // Error messages for user.
165 $msg = new ActionErrors(); // Notification messages (not errrors) for user.
166
167 // Create an instance of ttUser class. This gets us most of user details.
168 import('ttUser');
169 $user = new ttUser(null, $auth->getUserId());
170 if ($user->custom_logo) {
171   $smarty->assign('custom_logo', 'images/'.$user->team_id.'.png');
172   $smarty->assign('mobile_custom_logo', '../images/'.$user->team_id.'.png');
173 }
174 $smarty->assign('user', $user);
175
176 // Localization.
177 import('I18n');
178 $i18n = new I18n();
179
180 // Determine the language to use.
181 $lang = $user->lang;
182 if (!$lang) {
183   if (defined('LANG_DEFAULT'))
184     $lang = LANG_DEFAULT;
185
186   // If we still do not have the language get it from the browser.
187   if (!$lang) {
188     $lang = $i18n->getBrowserLanguage();
189
190     // Finally - English is the default.
191     if (!$lang) {
192       $lang = 'en';
193     }
194   }
195 }
196
197 // Load i18n file.
198 $i18n->load($lang);
199
200 // Assign things for smarty to use in template files.
201 $smarty->assign('i18n', $i18n->keys);
202 $smarty->assign('err', $err);
203 $smarty->assign('msg', $msg);
204
205 // TODO: move this code out of here to the files that use it.
206
207 // We use js/strftime.js to print dates in JavaScript (in DateField controls).
208 // One of our date formats (%d.%m.%Y %a) prints a localized short weekday name (%a).
209 // The init_js_date_locale function iniitializes Date.ext.locales array in js/strftime.js for our language
210 // so that we could print localized short weekday names.
211 //
212 // JavaScript usage (see http://hacks.bluesmoon.info/strftime/localisation.html).
213 //
214 // var d = new Date();
215 // d.locale = "fr";           // Remember to initialize locale.
216 // d.strftime("%d.%m.%Y %a"); // This will output a localized %a as in "31.05.2013 Ven"
217
218 // Initialize date locale for JavaScript.
219 init_js_date_locale();
220
221 function init_js_date_locale()
222 {
223   global $i18n, $smarty;
224   $lang = $i18n->lang;
225
226   $days = $i18n->weekdayNames;
227   $short_day_names = array();
228   foreach($days as $k => $v) {
229     $short_day_names[$k] = mb_substr($v, 0, 3, 'utf-8');
230   }
231
232   /*
233   $months = $i18n->monthNames;
234   $short_month_names = array();
235   foreach ($months as $k => $v) {
236     $short_month_names[$k] = mb_substr($v, 0, 3, 'utf-8');
237   }
238   $js = "Date.ext.locales['$lang'] = {
239       a: ['" . join("', '", $short_day_names) . "'],
240       A: ['" . join("', '", $days) . "'],
241       b: ['" . join("', '", $short_month_names) . "'],
242       B: ['" . join("', '", $months) . "'],
243       c: '%a %d %b %Y %T %Z',
244       p: ['', ''],
245       P: ['', ''],
246       x: '%Y-%m-%d',
247       X: '%T'
248     };"; */
249   // We use %a in one of date formats. Therefore, simplified code here (instead of the above block).
250   // %p is also used on the Profile page in 12-hour time format example. Note that %p is not localized.
251   $js = "Date.ext.locales['$lang'] = {
252       a: ['" . join("', '", $short_day_names) . "'],
253       p: ['AM', 'PM']
254     };";
255   $smarty->assign('js_date_locale', $js);
256 }