Fixed export and import for locking specification.
[timetracker.git] / WEB-INF / lib / ttExportHelper.class.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 import('ttTeamHelper');
30 import('ttTimeHelper');
31
32 // ttExportHelper - this class is used to export team data to a file.
33 class ttExportHelper {
34   var $fileName    = null;    // Name of the file with data.
35   
36   // The following arrays are maps between entity ids in the file versus the database.
37   // We write to the file sequentially (1,2,3...) while in the database the entities have different ids.
38   var $userMap     = array(); // User ids.
39   var $projectMap  = array(); // Project ids.
40   var $taskMap     = array(); // Task ids.
41   var $clientMap   = array(); // Client ids.
42   var $invoiceMap  = array(); // Invoice ids.
43   var $customFieldMap       = array(); // Custom field ids.
44   var $customFieldOptionMap = array(); // Custop field option ids.
45   var $logMap      = array(); // Time log ids.
46     
47   // createDataFile creates a file with all data for a given team.
48   function createDataFile($compress = false) {
49     global $user;
50
51     // Create a temporary file.
52     $dirName = dirname(TEMPLATE_DIR . '_c/.');
53     $tmp_file = tempnam($dirName, 'tt');
54
55     // Open the file for writing.
56     $file = fopen($tmp_file, 'wb');
57     if (!$file) return false;
58     
59     // Write XML to the file.
60     fwrite($file, "<?xml version=\"1.0\"?>\n");
61     fwrite($file, "<pack>\n");
62     
63     // Write team info.
64     fwrite($file, "<team currency=\"".$user->currency."\" lock_spec=\"".$user->lock_spec."\" lock_interval=\"".$user->lock_interval."\" lang=\"".$user->lang."\" decimal_mark=\"".$user->decimal_mark."\" date_format=\"".$user->date_format."\" time_format=\"".$user->time_format."\" week_start=\"".$user->week_start.
65       "\" plugins=\"".$user->plugins."\" tracking_mode=\"".$user->tracking_mode."\" record_type=\"".$user->record_type."\">\n");
66     fwrite($file, "  <name><![CDATA[".$user->team."]]></name>\n");
67     fwrite($file, "  <address><![CDATA[".$user->address."]]></address>\n");
68     fwrite($file, "</team>\n");
69     
70     // Prepare user map.
71     $users = ttTeamHelper::getAllUsers($user->team_id, true);
72     foreach ($users as $key=>$user_item)
73       $this->userMap[$user_item['id']] = $key + 1;
74       
75     // Prepare project map.
76     $projects = ttTeamHelper::getAllProjects($user->team_id, true);
77     foreach ($projects as $key=>$project_item)
78       $this->projectMap[$project_item['id']] = $key + 1;
79
80     // Prepare task map.
81     $tasks = ttTeamHelper::getAllTasks($user->team_id, true);
82     foreach ($tasks as $key=>$task_item)
83       $this->taskMap[$task_item['id']] = $key + 1;
84       
85     // Prepare client map.
86     $clients = ttTeamHelper::getAllClients($user->team_id, true);
87     foreach ($clients as $key=>$client_item)
88       $this->clientMap[$client_item['id']] = $key + 1;      
89
90     // Prepare invoice map.
91     $invoices = ttTeamHelper::getAllInvoices();
92     foreach ($invoices as $key=>$invoice_item)
93       $this->invoiceMap[$invoice_item['id']] = $key + 1;   
94
95     // Prepare custom fields map.
96     $custom_fields = ttTeamHelper::getAllCustomFields($user->team_id);
97     foreach ($custom_fields as $key=>$custom_field)
98       $this->customFieldMap[$custom_field['id']] = $key + 1;  
99
100     // Prepare custom field options map.
101     $custom_field_options = ttTeamHelper::getAllCustomFieldOptions($user->team_id);
102     foreach ($custom_field_options as $key=>$option)
103       $this->customFieldOptionMap[$option['id']] = $key + 1;  
104       
105     // Write users.
106     fwrite($file, "<users>\n");
107     foreach ($users as $user_item) {
108       fwrite($file, "  <user id=\"".$this->userMap[$user_item['id']]."\" login=\"".htmlentities($user_item['login'])."\" password=\"".$user_item['password']."\" role=\"".$user_item['role']."\" client_id=\"".$this->clientMap[$user_item['client_id']]."\" rate=\"".$user_item['rate']."\" email=\"".$user_item['email']."\" status=\"".$user_item['status']."\">\n");
109       fwrite($file, "    <name><![CDATA[".$user_item['name']."]]></name>\n");
110       fwrite($file, "  </user>\n");
111     }
112     fwrite($file, "</users>\n");
113
114     // Write tasks.
115     fwrite($file, "<tasks>\n");
116     foreach ($tasks as $task_item) {
117       fwrite($file, "  <task id=\"".$this->taskMap[$task_item['id']]."\" status=\"".$task_item['status']."\">\n");
118       fwrite($file, "    <name><![CDATA[".$task_item['name']."]]></name>\n");
119       fwrite($file, "    <description><![CDATA[".$task_item['description']."]]></description>\n");
120       fwrite($file, "  </task>\n");
121     }
122     fwrite($file, "</tasks>\n");
123     unset($tasks);
124
125     // Write projects.
126     fwrite($file, "<projects>\n");
127     foreach ($projects as $project_item) {
128       if($project_item['tasks']){
129         $tasks = explode(',', $project_item['tasks']);
130         $tasks_mapped = array();
131         foreach ($tasks as $item)
132           $tasks_mapped[] = $this->taskMap[$item];
133         $tasks_str = implode(',', $tasks_mapped);
134       }
135       fwrite($file, "  <project id=\"".$this->projectMap[$project_item['id']]."\" tasks=\"".$tasks_str."\" status=\"".$project_item['status']."\">\n");
136       fwrite($file, "    <name><![CDATA[".$project_item['name']."]]></name>\n");
137       fwrite($file, "    <description><![CDATA[".$project_item['description']."]]></description>\n");
138       fwrite($file, "  </project>\n");
139     }
140     fwrite($file, "</projects>\n");
141     unset($projects);
142
143     // Write user to project binds.
144     fwrite($file, "<user_project_binds>\n");
145     $user_binds = ttTeamHelper::getUserToProjectBinds($user->team_id);
146     foreach ($user_binds as $bind) {
147       $user_id = $this->userMap[$bind['user_id']];
148       $project_id = $this->projectMap[$bind['project_id']];
149       fwrite($file, "  <user_project_bind user_id=\"{$user_id}\" project_id=\"{$project_id}\" rate=\"".$bind['rate']."\" status=\"".$bind['status']."\"/>\n");
150     }
151     fwrite($file, "</user_project_binds>\n");
152     unset($user_binds);
153     
154     // Write clients.
155     fwrite($file, "<clients>\n");
156     foreach ($clients as $client_item) {
157       if($client_item['projects']){
158         $projects = explode(',', $client_item['projects']);
159         $projects_mapped = array();
160         foreach ($projects as $item)
161           $projects_mapped[] = $this->projectMap[$item];
162         $projects_str = implode(',', $projects_mapped);
163       }
164       fwrite($file, "  <client id=\"".$this->clientMap[$client_item['id']]."\" tax=\"".$client_item['tax']."\" projects=\"".$projects_str."\" status=\"".$client_item['status']."\">\n");
165       fwrite($file, "    <name><![CDATA[".$client_item['name']."]]></name>\n");
166       fwrite($file, "    <address><![CDATA[".$client_item['address']."]]></address>\n");
167       fwrite($file, "  </client>\n");
168     }
169     fwrite($file, "</clients>\n");
170     unset($clients);
171
172     // Write invoices.
173     fwrite($file, "<invoices>\n");
174     foreach ($invoices as $invoice_item) {
175       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");
176       fwrite($file, "    <name><![CDATA[".$invoice_item['name']."]]></name>\n");
177       fwrite($file, "  </invoice>\n");
178     }
179     fwrite($file, "</invoices>\n");
180     unset($invoices);
181
182     // Write custom fields.
183     fwrite($file, "<custom_fields>\n");
184     foreach ($custom_fields as $custom_field) {
185       fwrite($file, "  <custom_field id=\"".$this->customFieldMap[$custom_field['id']]."\" type=\"".$custom_field['type']."\" required=\"".$custom_field['required']."\" status=\"".$custom_field['status']."\">\n");
186       fwrite($file, "    <label><![CDATA[".$custom_field['label']."]]></label>\n");
187       fwrite($file, "  </custom_field>\n");
188     }
189     fwrite($file, "</custom_fields>\n");
190     unset($custom_fields);
191
192     // Write custom field options.
193     fwrite($file, "<custom_field_options>\n");
194     foreach ($custom_field_options as $option) {
195       fwrite($file, "  <custom_field_option id=\"".$this->customFieldOptionMap[$option['id']]."\" field_id=\"".$this->customFieldMap[$option['field_id']]."\">\n");
196       fwrite($file, "    <value><![CDATA[".$option['value']."]]></value>\n");
197       fwrite($file, "  </custom_field_option>\n");
198     }
199     fwrite($file, "</custom_field_options>\n");
200     unset($custom_field_options);
201     
202     // Write time log entries.
203     fwrite($file, "<log>\n");
204     $key = 0;
205     foreach ($users as $user_item) {
206       $records = ttTimeHelper::getAllRecords($user_item['id']);
207       foreach ($records as $record) {
208         $key++;
209         $this->logMap[$record['id']] = $key;   
210         fwrite($file, "  <log_item id=\"$key\" timestamp=\"".$record['timestamp']."\" 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']."\" status=\"".$record['status']."\">\n");
211         fwrite($file, "    <comment><![CDATA[".$record['comment']."]]></comment>\n");
212         fwrite($file, "  </log_item>\n");
213       }
214     }
215     fwrite($file, "</log>\n");
216     unset($records);
217     
218     // Write custom field log.
219     $custom_field_log = ttTeamHelper::getCustomFieldLog($user->team_id);
220     fwrite($file, "<custom_field_log>\n");
221     foreach ($custom_field_log as $entry) {
222       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");
223       fwrite($file, "    <value><![CDATA[".$entry['value']."]]></value>\n");
224       fwrite($file, "  </custom_field_log_entry>\n");
225     }
226     fwrite($file, "</custom_field_log>\n");
227     unset($custom_field_log);
228     
229     // Write expense items.
230     $expense_items = ttTeamHelper::getExpenseItems($user->team_id);
231     fwrite($file, "<expense_items>\n");
232     foreach ($expense_items as $expense_item) {
233       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']]."\" status=\"".$expense_item['status']."\">\n");
234       fwrite($file, "    <name><![CDATA[".$expense_item['name']."]]></name>\n");
235       fwrite($file, "  </expense_item>\n");
236     }
237     fwrite($file, "</expense_items>\n");
238     unset($expense_items);
239         
240     // Write fav reports.
241     fwrite($file, "<fav_reports>\n");
242     $fav_reports = ttTeamHelper::getFavReports($user->team_id);
243     foreach ($fav_reports as $fav_report) {
244       $user_list = '';
245       if (strlen($fav_report['users']) > 0) {
246         $arr = explode(',', $fav_report['users']);
247         foreach ($arr as $k=>$v) {
248           if (array_key_exists($arr[$k], $this->userMap))
249             $user_list .= (strlen($user_list) == 0? '' : ',').$this->userMap[$v];
250         }
251       }
252       fwrite($file, "\t<fav_report user_id=\"".$this->userMap[$fav_report['user_id']]."\"".
253         " client_id=\"".$this->clientMap[$fav_report['client_id']]."\"".
254         " cf_1_option_id=\"".$this->customFieldOptionMap[$fav_report['cf_1_option_id']]."\"".
255         " project_id=\"".$this->projectMap[$fav_report['project_id']]."\"".
256         " task_id=\"".$this->taskMap[$fav_report['task_id']]."\"".
257         " billable=\"".$fav_report['billable']."\"".
258         " users=\"".$user_list."\"".
259         " period=\"".$fav_report['period']."\"".
260         " period_start=\"".$fav_report['period_start']."\"".
261         " period_end=\"".$fav_report['period_end']."\"".
262         " show_client=\"".$fav_report['show_client']."\"".
263         " show_invoice=\"".$fav_report['show_invoice']."\"".
264         " show_project=\"".$fav_report['show_project']."\"".
265         " show_start=\"".$fav_report['show_start']."\"".
266         " show_duration=\"".$fav_report['show_duration']."\"".
267         " show_cost=\"".$fav_report['show_cost']."\"".
268         " show_task=\"".$fav_report['show_task']."\"".
269         " show_end=\"".$fav_report['show_end']."\"".
270         " show_note=\"".$fav_report['show_note']."\"".
271         " show_custom_field_1=\"".$fav_report['show_custom_field_1']."\"".
272         " group_by=\"".$fav_report['group_by']."\"".
273         " show_totals_only=\"".$fav_report['show_totals_only']."\">\n");
274         //" sort_by=\"".$fav_report['sort_by']."\"".
275         //" show_empty_days=\"".$fav_report['show_empty_days']."\">\n");
276       fwrite($file, "\t\t<name><![CDATA[".$fav_report["name"]."]]></name>\n");
277       fwrite($file, "\t</fav_report>\n");
278     }
279     fwrite($file, "</fav_reports>\n");
280     unset($fav_reports);
281
282     // Cleanup.
283     unset($users);
284     $this->userMap = array();
285     $this->projectMap = array();
286     $this->taskMap = array();
287     
288     fwrite($file, "</pack>\n");
289     fclose($file);
290     
291     if ($compress) {
292       $this->fileName = tempnam($dirName, 'tt');
293       $this->compress($tmp_file, $this->fileName);
294       unlink($tmp_file);
295     } else
296       $this->fileName = $tmp_file;
297         
298         return true;
299   }
300   
301   // getFileName - returns file name.
302   function getFileName() {
303     return $this->fileName;
304   }
305
306   // compress - compresses the content of the $in file into $out file.
307   function compress($in, $out) {
308         // Initial checks of file names and permissions.
309     if (!file_exists($in) || !is_readable ($in))
310       return false;
311     if ((!file_exists($out) && !is_writable(dirname($out))) || (file_exists($out) && !is_writable($out)))
312       return false;
313
314     $in_file = fopen($in, 'rb');
315
316     if (function_exists('bzopen')) {
317       if (!$out_file = bzopen($out, 'w'))
318         return false;
319
320       while (!feof ($in_file)) {
321         $buffer = fread($in_file, 4096);
322         bzwrite($out_file, $buffer, 4096);
323       }
324       bzclose($out_file);
325     }
326     fclose ($in_file);
327     return true;
328   }
329 }