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.
11 // | There are only two ways to violate the license:
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).
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).
21 // | This license applies to this document only, not any other software
22 // | that it may be combined with.
24 // +----------------------------------------------------------------------+
26 // | https://www.anuko.com/time_tracker/credits.htm
27 // +----------------------------------------------------------------------+
29 import('ttTeamHelper');
30 import('ttTimeHelper');
31 import('ttGroupExportHelper');
33 // ttOrgExportHelper - this class is a future replacement for ttExportHelper.
34 // Currently, it is work in progress.
35 // When done, it should handle export of organizations containing multiple groups.
36 class ttOrgExportHelper {
37 // TODO: we need a constructor...
38 var $fileName = null; // Name of the file with data.
40 // The following arrays are maps between entity ids in the file versus the database.
41 // We write to the file sequentially (1,2,3...) while in the database the entities have different ids.
42 var $userMap = array(); // User ids.
43 var $roleMap = array(); // Role ids.
44 var $projectMap = array(); // Project ids.
45 var $taskMap = array(); // Task ids.
46 var $clientMap = array(); // Client ids.
47 var $invoiceMap = array(); // Invoice ids.
48 var $customFieldMap = array(); // Custom field ids.
49 var $customFieldOptionMap = array(); // Custop field option ids.
50 var $logMap = array(); // Time log ids.
52 // createDataFile creates a file with all data for a given group.
53 function createDataFile($compress = false) {
56 // Create a temporary file.
57 $dirName = dirname(TEMPLATE_DIR . '_c/.');
58 $tmp_file = tempnam($dirName, 'tt');
60 // Open the file for writing.
61 $file = fopen($tmp_file, 'wb');
62 if (!$file) return false;
64 // Write XML to the file.
65 fwrite($file, "<?xml version=\"1.0\"?>\n");
66 fwrite($file, "<org>\n");
69 fwrite($file, "<group currency=\"".$user->currency."\" decimal_mark=\"".$user->decimal_mark."\" lang=\"".$user->lang.
70 "\" date_format=\"".$user->date_format."\" time_format=\"".$user->time_format."\" week_start=\"".$user->week_start.
71 "\" tracking_mode=\"".$user->tracking_mode."\" project_required=\"".$user->project_required."\" task_required=\"".$user->task_required.
72 "\" record_type=\"".$user->record_type."\" bcc_email=\"".$user->bcc_email.
73 "\" plugins=\"".$user->plugins."\" lock_spec=\"".$user->lock_spec."\" workday_minutes=\"".$user->workday_minutes.
74 "\" config=\"".$user->config.
76 fwrite($file, " <name><![CDATA[".$user->group_name."]]></name>\n");
77 fwrite($file, " <allow_ip><![CDATA[".$user->allow_ip."]]></allow_ip>\n");
78 fwrite($file, " <password_complexity><![CDATA[".$user->password_complexity."]]></password_complexity>\n");
79 fwrite($file, "</group>\n");
82 $roles = $this->getRoles();
83 foreach ($roles as $key=>$role_item)
84 $this->roleMap[$role_item['id']] = $key + 1;
87 $users = $this->getUsers();
88 foreach ($users as $key=>$user_item)
89 $this->userMap[$user_item['id']] = $key + 1;
91 // Prepare project map.
92 $projects = ttTeamHelper::getAllProjects($user->group_id, true);
93 foreach ($projects as $key=>$project_item)
94 $this->projectMap[$project_item['id']] = $key + 1;
97 $tasks = ttTeamHelper::getAllTasks($user->group_id, true);
98 foreach ($tasks as $key=>$task_item)
99 $this->taskMap[$task_item['id']] = $key + 1;
101 // Prepare client map.
102 $clients = ttTeamHelper::getAllClients($user->group_id, true);
103 foreach ($clients as $key=>$client_item)
104 $this->clientMap[$client_item['id']] = $key + 1;
106 // Prepare invoice map.
107 $invoices = ttTeamHelper::getAllInvoices();
108 foreach ($invoices as $key=>$invoice_item)
109 $this->invoiceMap[$invoice_item['id']] = $key + 1;
111 // Prepare custom fields map.
112 $custom_fields = ttTeamHelper::getAllCustomFields($user->group_id);
113 foreach ($custom_fields as $key=>$custom_field)
114 $this->customFieldMap[$custom_field['id']] = $key + 1;
116 // Prepare custom field options map.
117 $custom_field_options = ttTeamHelper::getAllCustomFieldOptions($user->group_id);
118 foreach ($custom_field_options as $key=>$option)
119 $this->customFieldOptionMap[$option['id']] = $key + 1;
122 fwrite($file, "<roles>\n");
123 foreach ($roles as $role) {
124 fwrite($file, " <role id=\"".$this->roleMap[$role['id']]."\" rank=\"".$role['rank']."\"".
125 " rights=\"".$role['rights']."\" status=\"".$role['status']."\">\n");
126 fwrite($file, " <name><![CDATA[".$role['name']."]]></name>\n");
127 fwrite($file, " </role>\n");
129 fwrite($file, "</roles>\n");
133 fwrite($file, "<users>\n");
134 foreach ($users as $user_item) {
135 $role_id = $user_item['rank'] == 512 ? 0 : $this->roleMap[$user_item['role_id']]; // Special role_id 0 (not null) for top manager.
136 fwrite($file, " <user id=\"".$this->userMap[$user_item['id']]."\" login=\"".htmlentities($user_item['login'])."\" password=\"".$user_item['password']."\" role_id=\"".$role_id."\" client_id=\"".$this->clientMap[$user_item['client_id']]."\" rate=\"".$user_item['rate']."\" email=\"".$user_item['email']."\" status=\"".$user_item['status']."\">\n");
137 fwrite($file, " <name><![CDATA[".$user_item['name']."]]></name>\n");
138 fwrite($file, " </user>\n");
140 fwrite($file, "</users>\n");
143 fwrite($file, "<tasks>\n");
144 foreach ($tasks as $task_item) {
145 fwrite($file, " <task id=\"".$this->taskMap[$task_item['id']]."\" status=\"".$task_item['status']."\">\n");
146 fwrite($file, " <name><![CDATA[".$task_item['name']."]]></name>\n");
147 fwrite($file, " <description><![CDATA[".$task_item['description']."]]></description>\n");
148 fwrite($file, " </task>\n");
150 fwrite($file, "</tasks>\n");
154 fwrite($file, "<projects>\n");
155 foreach ($projects as $project_item) {
156 if($project_item['tasks']){
157 $tasks = explode(',', $project_item['tasks']);
158 $tasks_mapped = array();
159 foreach ($tasks as $item)
160 $tasks_mapped[] = $this->taskMap[$item];
161 $tasks_str = implode(',', $tasks_mapped);
163 fwrite($file, " <project id=\"".$this->projectMap[$project_item['id']]."\" tasks=\"".$tasks_str."\" status=\"".$project_item['status']."\">\n");
164 fwrite($file, " <name><![CDATA[".$project_item['name']."]]></name>\n");
165 fwrite($file, " <description><![CDATA[".$project_item['description']."]]></description>\n");
166 fwrite($file, " </project>\n");
168 fwrite($file, "</projects>\n");
171 // Write user to project binds.
172 fwrite($file, "<user_project_binds>\n");
173 $user_binds = ttTeamHelper::getUserToProjectBinds($user->group_id);
174 foreach ($user_binds as $bind) {
175 $user_id = $this->userMap[$bind['user_id']];
176 $project_id = $this->projectMap[$bind['project_id']];
177 fwrite($file, " <user_project_bind user_id=\"{$user_id}\" project_id=\"{$project_id}\" rate=\"".$bind['rate']."\" status=\"".$bind['status']."\"/>\n");
179 fwrite($file, "</user_project_binds>\n");
183 fwrite($file, "<clients>\n");
184 foreach ($clients as $client_item) {
185 if($client_item['projects']){
186 $projects = explode(',', $client_item['projects']);
187 $projects_mapped = array();
188 foreach ($projects as $item)
189 $projects_mapped[] = $this->projectMap[$item];
190 $projects_str = implode(',', $projects_mapped);
192 fwrite($file, " <client id=\"".$this->clientMap[$client_item['id']]."\" tax=\"".$client_item['tax']."\" projects=\"".$projects_str."\" status=\"".$client_item['status']."\">\n");
193 fwrite($file, " <name><![CDATA[".$client_item['name']."]]></name>\n");
194 fwrite($file, " <address><![CDATA[".$client_item['address']."]]></address>\n");
195 fwrite($file, " </client>\n");
197 fwrite($file, "</clients>\n");
201 fwrite($file, "<invoices>\n");
202 foreach ($invoices as $invoice_item) {
203 fwrite($file, " <invoice id=\"".$this->invoiceMap[$invoice_item['id']]."\" date=\"".$invoice_item['date']."\" client_id=\"".$this->clientMap[$invoice_item['client_id']]."\" status=\"".$invoice_item['status']."\">\n");
204 fwrite($file, " <name><![CDATA[".$invoice_item['name']."]]></name>\n");
205 fwrite($file, " </invoice>\n");
207 fwrite($file, "</invoices>\n");
210 // Write custom fields.
211 fwrite($file, "<custom_fields>\n");
212 foreach ($custom_fields as $custom_field) {
213 fwrite($file, " <custom_field id=\"".$this->customFieldMap[$custom_field['id']]."\" type=\"".$custom_field['type']."\" required=\"".$custom_field['required']."\" status=\"".$custom_field['status']."\">\n");
214 fwrite($file, " <label><![CDATA[".$custom_field['label']."]]></label>\n");
215 fwrite($file, " </custom_field>\n");
217 fwrite($file, "</custom_fields>\n");
218 unset($custom_fields);
220 // Write custom field options.
221 fwrite($file, "<custom_field_options>\n");
222 foreach ($custom_field_options as $option) {
223 fwrite($file, " <custom_field_option id=\"".$this->customFieldOptionMap[$option['id']]."\" field_id=\"".$this->customFieldMap[$option['field_id']]."\">\n");
224 fwrite($file, " <value><![CDATA[".$option['value']."]]></value>\n");
225 fwrite($file, " </custom_field_option>\n");
227 fwrite($file, "</custom_field_options>\n");
228 unset($custom_field_options);
230 // Write monthly quotas.
231 $quotas = ttTeamHelper::getMonthlyQuotas($user->group_id);
232 fwrite($file, "<monthly_quotas>\n");
233 foreach ($quotas as $quota) {
234 fwrite($file, " <monthly_quota year=\"".$quota['year']."\" month=\"".$quota['month']."\" minutes=\"".$quota['minutes']."\"/>\n");
236 fwrite($file, "</monthly_quotas>\n");
238 // Write time log entries.
239 fwrite($file, "<log>\n");
241 foreach ($users as $user_item) {
242 $records = ttTimeHelper::getAllRecords($user_item['id']);
243 foreach ($records as $record) {
245 $this->logMap[$record['id']] = $key;
246 fwrite($file, " <log_item id=\"$key\" user_id=\"".$this->userMap[$record['user_id']]."\" date=\"".$record['date']."\" start=\"".$record['start']."\" finish=\"".$record['finish']."\" duration=\"".($record['start']?"":$record['duration'])."\" client_id=\"".$this->clientMap[$record['client_id']]."\" project_id=\"".$this->projectMap[$record['project_id']]."\" task_id=\"".$this->taskMap[$record['task_id']]."\" invoice_id=\"".$this->invoiceMap[$record['invoice_id']]."\" billable=\"".$record['billable']."\" paid=\"".$record['paid']."\" status=\"".$record['status']."\">\n");
247 fwrite($file, " <comment><![CDATA[".$record['comment']."]]></comment>\n");
248 fwrite($file, " </log_item>\n");
251 fwrite($file, "</log>\n");
254 // Write custom field log.
255 $custom_field_log = ttTeamHelper::getCustomFieldLog($user->group_id);
256 fwrite($file, "<custom_field_log>\n");
257 foreach ($custom_field_log as $entry) {
258 fwrite($file, " <custom_field_log_entry log_id=\"".$this->logMap[$entry['log_id']]."\" field_id=\"".$this->customFieldMap[$entry['field_id']]."\" option_id=\"".$this->customFieldOptionMap[$entry['option_id']]."\" status=\"".$entry['status']."\">\n");
259 fwrite($file, " <value><![CDATA[".$entry['value']."]]></value>\n");
260 fwrite($file, " </custom_field_log_entry>\n");
262 fwrite($file, "</custom_field_log>\n");
263 unset($custom_field_log);
265 // Write expense items.
266 $expense_items = ttTeamHelper::getExpenseItems($user->group_id);
267 fwrite($file, "<expense_items>\n");
268 foreach ($expense_items as $expense_item) {
269 fwrite($file, " <expense_item date=\"".$expense_item['date']."\" user_id=\"".$this->userMap[$expense_item['user_id']]."\" client_id=\"".$this->clientMap[$expense_item['client_id']]."\" project_id=\"".$this->projectMap[$expense_item['project_id']]."\" cost=\"".$expense_item['cost']."\" invoice_id=\"".$this->invoiceMap[$expense_item['invoice_id']]."\" paid=\"".$expense_item['paid']."\" status=\"".$expense_item['status']."\">\n");
270 fwrite($file, " <name><![CDATA[".$expense_item['name']."]]></name>\n");
271 fwrite($file, " </expense_item>\n");
273 fwrite($file, "</expense_items>\n");
274 unset($expense_items);
276 // Write fav reports.
277 fwrite($file, "<fav_reports>\n");
278 $fav_reports = ttTeamHelper::getFavReports($user->group_id);
279 foreach ($fav_reports as $fav_report) {
281 if (strlen($fav_report['users']) > 0) {
282 $arr = explode(',', $fav_report['users']);
283 foreach ($arr as $k=>$v) {
284 if (array_key_exists($arr[$k], $this->userMap))
285 $user_list .= (strlen($user_list) == 0? '' : ',').$this->userMap[$v];
288 fwrite($file, " <fav_report user_id=\"".$this->userMap[$fav_report['user_id']]."\"".
289 " client_id=\"".$this->clientMap[$fav_report['client_id']]."\"".
290 " cf_1_option_id=\"".$this->customFieldOptionMap[$fav_report['cf_1_option_id']]."\"".
291 " project_id=\"".$this->projectMap[$fav_report['project_id']]."\"".
292 " task_id=\"".$this->taskMap[$fav_report['task_id']]."\"".
293 " billable=\"".$fav_report['billable']."\"".
294 " users=\"".$user_list."\"".
295 " period=\"".$fav_report['period']."\"".
296 " period_start=\"".$fav_report['period_start']."\"".
297 " period_end=\"".$fav_report['period_end']."\"".
298 " show_client=\"".$fav_report['show_client']."\"".
299 " show_invoice=\"".$fav_report['show_invoice']."\"".
300 " show_paid=\"".$fav_report['show_paid']."\"".
301 " show_ip=\"".$fav_report['show_ip']."\"".
302 " show_project=\"".$fav_report['show_project']."\"".
303 " show_start=\"".$fav_report['show_start']."\"".
304 " show_duration=\"".$fav_report['show_duration']."\"".
305 " show_cost=\"".$fav_report['show_cost']."\"".
306 " show_task=\"".$fav_report['show_task']."\"".
307 " show_end=\"".$fav_report['show_end']."\"".
308 " show_note=\"".$fav_report['show_note']."\"".
309 " show_custom_field_1=\"".$fav_report['show_custom_field_1']."\"".
310 " show_work_units=\"".$fav_report['show_work_units']."\"".
311 " group_by1=\"".$fav_report['group_by1']."\"".
312 " group_by2=\"".$fav_report['group_by2']."\"".
313 " group_by3=\"".$fav_report['group_by3']."\"".
314 " show_totals_only=\"".$fav_report['show_totals_only']."\">\n");
315 fwrite($file, " <name><![CDATA[".$fav_report["name"]."]]></name>\n");
316 fwrite($file, " </fav_report>\n");
318 fwrite($file, "</fav_reports>\n");
323 $this->roleMap = array();
324 $this->userMap = array();
325 $this->projectMap = array();
326 $this->taskMap = array();
328 fwrite($file, "</org>\n");
332 $this->fileName = tempnam($dirName, 'tt');
333 $this->compress($tmp_file, $this->fileName);
336 $this->fileName = $tmp_file;
341 // getFileName - returns file name.
342 function getFileName() {
343 return $this->fileName;
346 // compress - compresses the content of the $in file into $out file.
347 function compress($in, $out) {
348 // Initial checks of file names and permissions.
349 if (!file_exists($in) || !is_readable ($in))
351 if ((!file_exists($out) && !is_writable(dirname($out))) || (file_exists($out) && !is_writable($out)))
354 $in_file = fopen($in, 'rb');
356 if (function_exists('bzopen')) {
357 if (!$out_file = bzopen($out, 'w'))
360 while (!feof ($in_file)) {
361 $buffer = fread($in_file, 4096);
362 bzwrite($out_file, $buffer, 4096);
371 * Note about the utility functions below.
372 * We have roughly 4 groups of operations:
373 * 1) Regular system usage for tracking time, etc.
374 * 2) Registration process - used infrequently.
375 * 3) Admin usage - used infrequently.
376 * 4) Export - used infrequently.
378 * It is tempting to have a generic function to get things done for
379 * all situations. However, as registration, export and admin access are one-off
380 * operations, while regular system usage is daily and must be efficient,
381 * the current approach is to have SEPARATE functions for each mode.
383 * This is because each mode requires a slightly different approach,
384 * and we don't want to over-complicate things.
387 // getRoles - obtains all roles defined for group.
388 function getRoles() {
390 $mdb2 = getConnection();
393 $sql = "select * from tt_roles where group_id = $user->group_id";
394 $res = $mdb2->query($sql);
396 if (!is_a($res, 'PEAR_Error')) {
397 while ($val = $res->fetchRow()) {
405 // The getUsers obtains all users in group for the purpose of export.
406 function getUsers() {
408 $mdb2 = getConnection();
410 $sql = "select u.*, r.rank from tt_users u left join tt_roles r on (u.role_id = r.id) where u.group_id = $user->group_id order by upper(u.name)"; // Note: deleted users are included.
411 $res = $mdb2->query($sql);
413 if (!is_a($res, 'PEAR_Error')) {
414 while ($val = $res->fetchRow()) {