Fixed export and import for locking specification.
[timetracker.git] / WEB-INF / lib / ttTeamHelper.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('ttUserHelper');
30 import('DateAndTime');
31
32 // Class ttTeamHelper - contains helper functions that operate with teams.
33 class ttTeamHelper {
34         
35   // The getUserCount function returns number of people in team.
36   static function getUserCount($team_id) {
37         $mdb2 = getConnection();
38     
39     $sql = "select count(id) as cnt from tt_users where team_id = $team_id and status = 1";
40     $res = $mdb2->query($sql);
41
42     if (!is_a($res, 'PEAR_Error')) {
43       $val = $res->fetchRow();
44       return $val['cnt'];
45     }
46     return false;
47   }
48   
49   // The getUsersForClient obtains all active and inactive users in a team that are relevant to a client.
50   static function getUsersForClient() {
51     global $user;
52     $mdb2 = getConnection();
53     
54     $sql = "select u.id, u.name from tt_user_project_binds upb
55       inner join tt_client_project_binds cpb on (upb.project_id = cpb.project_id and cpb.client_id = $user->client_id)
56       inner join tt_users u on (u.id = upb.user_id)
57       where (u.status = 1 or u.status = 0)
58       group by u.id
59       order by u.name";
60     $res = $mdb2->query($sql);
61     $user_list = array();
62     if (is_a($res, 'PEAR_Error'))
63       return false;
64     while ($val = $res->fetchRow()) {
65       $user_list[] = $val;
66     }
67     return $user_list;
68   }  
69
70   // The getActiveUsers obtains all active users in a given team.
71   static function getActiveUsers($options = null) {
72         global $user;
73     $mdb2 = getConnection();
74     
75     if (isset($options['getAllFields']))
76       $sql = "select * from tt_users where team_id = $user->team_id and status = 1 order by name";
77     else
78       $sql = "select id, name from tt_users where team_id = $user->team_id and status = 1 order by name";
79     $res = $mdb2->query($sql);
80     $user_list = array();
81     if (is_a($res, 'PEAR_Error'))
82       return false;
83     while ($val = $res->fetchRow()) {
84       $user_list[] = $val;
85     }
86
87     if (isset($options['putSelfFirst'])) {
88       // Put own entry at the front.
89       $cnt = count($user_list);
90       for($i = 0; $i < $cnt; $i++) {
91         if ($user_list[$i]['id'] == $user->id) {
92           $self = $user_list[$i]; // Found self.
93           array_unshift($user_list, $self); // Put own entry at the front.
94           array_splice($user_list, $i+1, 1); // Remove duplicate.
95         }
96       }
97     }      
98     return $user_list;
99   }
100   
101   
102   // The getUsers obtains all active and inactive (but not deleted) users in a given team.
103   static function getUsers() {
104         global $user;
105     $mdb2 = getConnection();
106     
107     $sql = "select id, name from tt_users where team_id = $user->team_id and (status = 1 or status = 0) order by name";
108     $res = $mdb2->query($sql);
109     $user_list = array();
110     if (is_a($res, 'PEAR_Error'))
111       return false;
112     while ($val = $res->fetchRow()) {
113       $user_list[] = $val;
114     }
115
116     return $user_list;
117   }
118   
119
120   // The getInactiveUsers obtains all inactive users in a given team.
121   static function getInactiveUsers($team_id, $all_fields = false) {
122     $mdb2 = getConnection();
123     
124     if ($all_fields)
125       $sql = "select * from tt_users where team_id = $team_id and status = 0 order by name";
126     else
127       $sql = "select id, name from tt_users where team_id = $team_id and status = 0 order by name";
128     $res = $mdb2->query($sql);
129     $result = array();
130     if (!is_a($res, 'PEAR_Error')) {
131       while ($val = $res->fetchRow()) {
132         $result[] = $val;
133       }
134       return $result;
135     }
136     return false;
137   }
138   
139   // The getAllUsers obtains all users in a given team.
140   static function getAllUsers($team_id, $all_fields = false) {
141     $mdb2 = getConnection();
142     
143     if ($all_fields)
144       $sql = "select * from tt_users where team_id = $team_id order by name";
145     else
146       $sql = "select id, name from tt_users where team_id = $team_id order by name";
147     $res = $mdb2->query($sql);
148     $result = array();
149     if (!is_a($res, 'PEAR_Error')) {
150       while ($val = $res->fetchRow()) {
151         $result[] = $val;
152       }
153       return $result;
154     }
155     return false;
156   }
157   
158   // getActiveProjects - returns an array of active projects for team.
159   static function getActiveProjects($team_id)
160   {
161         $result = array();
162     $mdb2 = getConnection();
163
164     $sql = "select id, name, description, tasks from tt_projects
165       where team_id = $team_id and status = 1 order by name";   
166     $res = $mdb2->query($sql);
167     $result = array();
168     if (!is_a($res, 'PEAR_Error')) {
169       while ($val = $res->fetchRow()) {
170         $result[] = $val;
171       }
172     }
173     return $result;
174   }
175   
176   // getInactiveProjects - returns an array of inactive projects for team.
177   static function getInactiveProjects($team_id)
178   {
179         $result = array();
180     $mdb2 = getConnection();
181     
182     $sql = "select id, name, description, tasks from tt_projects
183       where team_id = $team_id and status = 0 order by name";   
184     $res = $mdb2->query($sql);
185     $result = array();
186     if (!is_a($res, 'PEAR_Error')) {
187       while ($val = $res->fetchRow()) {
188         $result[] = $val;
189       }
190     }
191     return $result;
192   }
193   
194   // The getAllProjects obtains all projects in a given team.
195   static function getAllProjects($team_id, $all_fields = false) {
196     $mdb2 = getConnection();
197     
198     if ($all_fields)
199       $sql = "select * from tt_projects where team_id = $team_id order by status, name";
200     else
201       $sql = "select id, name from tt_projects where team_id = $team_id order by status, name";
202     $res = $mdb2->query($sql);
203     $result = array();
204     if (!is_a($res, 'PEAR_Error')) {
205       while ($val = $res->fetchRow()) {
206         $result[] = $val;
207       }
208       return $result;
209     }
210     return false;
211   }
212
213   // getActiveTasks - returns an array of active tasks for team.
214   static function getActiveTasks($team_id)
215   {
216         $result = array();
217     $mdb2 = getConnection();
218
219     $sql = "select id, name, description from tt_tasks where team_id = $team_id and status = 1 order by name";          
220     $res = $mdb2->query($sql);
221     $result = array();
222     if (!is_a($res, 'PEAR_Error')) {
223       while ($val = $res->fetchRow()) {
224         $result[] = $val;
225       }
226     }
227     return $result;
228   }
229   
230   // getInactiveTasks - returns an array of inactive tasks for team.
231   static function getInactiveTasks($team_id)
232   {
233         $result = array();
234     $mdb2 = getConnection();
235     
236     $sql = "select id, name, description from tt_tasks
237       where team_id = $team_id and status = 0 order by name";   
238     $res = $mdb2->query($sql);
239     $result = array();
240     if (!is_a($res, 'PEAR_Error')) {
241       while ($val = $res->fetchRow()) {
242         $result[] = $val;
243       }
244     }
245     return $result;
246   }
247     
248   // The getAllTasks obtains all tasks in a given team.
249   static function getAllTasks($team_id, $all_fields = false) {
250     $mdb2 = getConnection();
251     
252     if ($all_fields)
253       $sql = "select * from tt_tasks where team_id = $team_id order by status, name";
254     else
255       $sql = "select id, name from tt_tasks where team_id = $team_id order by status, name";
256     $res = $mdb2->query($sql);
257     $result = array();
258     if (!is_a($res, 'PEAR_Error')) {
259       while ($val = $res->fetchRow()) {
260         $result[] = $val;
261       }
262       return $result;
263     }
264     return false;
265   }
266   
267   // The getActiveClients returns an array of active clients for team.
268   static function getActiveClients($team_id, $all_fields = false)
269   {
270     $result = array();
271         $mdb2 = getConnection();
272     
273         if ($all_fields)
274       $sql = "select * from tt_clients where team_id = $team_id and status = 1 order by name";
275     else
276       $sql = "select id, name from tt_clients where team_id = $team_id and status = 1 order by name";
277         $res = $mdb2->query($sql);
278         $result = array();
279         if (!is_a($res, 'PEAR_Error')) {
280       while ($val = $res->fetchRow()) {
281         $result[] = $val;
282       }
283     }
284     return $result;
285   }
286   
287   // The getInactiveClients returns an array of inactive clients for team.
288   static function getInactiveClients($team_id, $all_fields = false)
289   {
290     $result = array();
291         $mdb2 = getConnection();
292     
293         if ($all_fields)
294       $sql = "select * from tt_clients where team_id = $team_id and status = 0 order by name";
295     else
296       $sql = "select id, name from tt_clients where team_id = $team_id and status = 0 order by name";
297         $res = $mdb2->query($sql);
298     $result = array();
299         if (!is_a($res, 'PEAR_Error')) {
300       while ($val = $res->fetchRow()) {
301         $result[] = $val;
302       }
303     }
304     return $result;
305   }
306   
307   // The getAllClients obtains all clients in a given team.
308   static function getAllClients($team_id, $all_fields = false) {
309     $mdb2 = getConnection();
310     
311     if ($all_fields)
312       $sql = "select * from tt_clients where team_id = $team_id order by status, name";
313     else
314       $sql = "select id, name from tt_clients where team_id = $team_id order by status, name";
315     $res = $mdb2->query($sql);
316     $result = array();
317     if (!is_a($res, 'PEAR_Error')) {
318       while ($val = $res->fetchRow()) {
319         $result[] = $val;
320       }
321       return $result;
322     }
323     return false;
324   }
325
326   // The getActiveInvoices returns an array of active invoices for team.
327   static function getActiveInvoices($localizeDates = true)
328   {
329         global $user;
330         
331     $result = array();
332         $mdb2 = getConnection();
333         
334         if (ROLE_CLIENT == $user->role && $user->client_id)
335           $client_part = " and i.client_id = $user->client_id";
336         
337         $sql = "select i.id, i.name, i.date, i.client_id, i.status, c.name as client_name from tt_invoices i 
338           left join tt_clients c on (c.id = i.client_id)
339           where i.status = 1 and i.team_id = $user->team_id $client_part order by i.name";
340     $res = $mdb2->query($sql);
341     $result = array();
342     if (!is_a($res, 'PEAR_Error')) {
343       $dt = new DateAndTime(DB_DATEFORMAT);
344       while ($val = $res->fetchRow()) {
345         if ($localizeDates) {
346           $dt->parseVal($val['date']);
347           $val['date'] = $dt->toString($user->date_format);
348         }
349         $result[] = $val;
350       }
351     }
352     return $result;
353   }
354   
355   // The getAllInvoices returns an array of all invoices for team.
356   static function getAllInvoices()
357   {
358         global $user;
359         
360     $result = array();
361         $mdb2 = getConnection();
362         
363         $sql = "select * from tt_invoices where team_id = $user->team_id";
364     $res = $mdb2->query($sql);
365     $result = array();
366     if (!is_a($res, 'PEAR_Error')) {
367       $dt = new DateAndTime(DB_DATEFORMAT);
368       while ($val = $res->fetchRow()) {
369         $result[] = $val;
370       }
371     }
372     return $result;
373   }
374   
375   // The getRecentInvoices returns an array of recent invoices (max 3) for a client.
376   static function getRecentInvoices($team_id, $client_id)
377   {
378         global $user;
379         
380     $result = array();
381         $mdb2 = getConnection();
382     
383         $sql = "select i.id, i.name from tt_invoices i 
384           left join tt_clients c on (c.id = i.client_id)
385           where i.team_id = $team_id and i.status = 1 and c.id = $client_id
386           order by i.id desc limit 3";
387     $res = $mdb2->query($sql);
388     $result = array();
389     if (!is_a($res, 'PEAR_Error')) {
390       $dt = new DateAndTime(DB_DATEFORMAT);
391       while ($val = $res->fetchRow()) {
392         $result[] = $val;
393       }
394     }
395     return $result;
396   }
397   
398   // getUserToProjectBinds - obtains all user to project binds for a team.
399   static function getUserToProjectBinds($team_id) {
400     $mdb2 = getConnection();
401       
402     $result = array();
403     $sql = "select * from tt_user_project_binds where user_id in (select id from tt_users where team_id = $team_id) order by user_id, status, project_id";
404     $res = $mdb2->query($sql);
405     $result = array();
406     if (!is_a($res, 'PEAR_Error')) {
407       while ($val = $res->fetchRow()) {
408         $result[] = $val;
409       }
410       return $result;
411     }
412     return false;
413   }
414   
415   // The getAllCustomFields obtains all custom fields in a given team.
416   static function getAllCustomFields($team_id) {
417     $mdb2 = getConnection();
418
419     $sql = "select * from tt_custom_fields where team_id = $team_id order by status";
420
421     $res = $mdb2->query($sql);
422     $result = array();
423     if (!is_a($res, 'PEAR_Error')) {
424       while ($val = $res->fetchRow()) {
425         $result[] = $val;
426       }
427       return $result;
428     }
429     return false;
430   }
431
432   // The getAllCustomFieldOptions obtains all custom field options in a given team.
433   static function getAllCustomFieldOptions($team_id) {
434     $mdb2 = getConnection();
435
436     $sql = "select * from tt_custom_field_options where field_id in (select id from tt_custom_fields where team_id = $team_id) order by id";
437
438     $res = $mdb2->query($sql);
439     $result = array();
440     if (!is_a($res, 'PEAR_Error')) {
441       while ($val = $res->fetchRow()) {
442         $result[] = $val;
443       }
444       return $result;
445     }
446     return false;
447   }
448   
449   // The getCustomFieldLog obtains all custom field log entries for a given team.
450   static function getCustomFieldLog($team_id) {
451     $mdb2 = getConnection();
452
453     $sql = "select * from tt_custom_field_log where field_id in (select id from tt_custom_fields where team_id = $team_id) order by id";
454
455     $res = $mdb2->query($sql);
456     $result = array();
457     if (!is_a($res, 'PEAR_Error')) {
458       while ($val = $res->fetchRow()) {
459         $result[] = $val;
460       }
461       return $result;
462     }
463     return false;
464   }
465     
466   // getFavReports - obtains all favorite reports for all users in team.
467   static function getFavReports($team_id) {
468     $mdb2 = getConnection();
469
470     $result = array();
471     $sql = "select * from tt_fav_reports where user_id in (select id from tt_users where team_id = $team_id)";
472     $res = $mdb2->query($sql);
473     $result = array();
474     if (!is_a($res, 'PEAR_Error')) {
475       while ($val = $res->fetchRow()) {
476         $result[] = $val;
477       }
478       return $result;
479     }
480     return false;
481   }
482   
483   // getExpenseItems - obtains all expense items for all users in team.
484   static function getExpenseItems($team_id) {
485     $mdb2 = getConnection();
486
487     $result = array();
488     $sql = "select * from tt_expense_items where user_id in (select id from tt_users where team_id = $team_id)";
489     $res = $mdb2->query($sql);
490     $result = array();
491     if (!is_a($res, 'PEAR_Error')) {
492       while ($val = $res->fetchRow()) {
493         $result[] = $val;
494       }
495       return $result;
496     }
497     return false;
498   }
499   
500   // getNotifications - obtains notification descriptions for team.
501   static function getNotifications($team_id) {
502     $mdb2 = getConnection();
503
504     $result = array();
505     $sql = "select c.id, c.cron_spec, c.email, fr.name from tt_cron c
506       left join tt_fav_reports fr on (fr.id = c.report_id)
507       where c.team_id = $team_id and c.status is not null"; 
508     $res = $mdb2->query($sql);
509     $result = array();
510     if (!is_a($res, 'PEAR_Error')) {
511       while ($val = $res->fetchRow()) {
512         $result[] = $val;
513       }
514       return $result;
515     }
516     return false;
517   }
518
519   // The getTeams function returns an array of all active teams on the server.
520   static function getTeams() {
521     $result = array();
522     $mdb2 = getConnection();
523     
524     $sql =  "select id, name, lang, timestamp from tt_teams where status = 1 order by id desc";
525     $res = $mdb2->query($sql);
526     $result = array();
527     if (!is_a($res, 'PEAR_Error')) {
528       while ($val = $res->fetchRow()) {
529         $val['date'] = substr($val['timestamp'], 0, 10); // Strip the time.
530         $result[] = $val;
531       }
532       return $result;
533     }
534     return false;
535   }
536   
537   // The markDeleted function marks the team and everything in it as deleted.
538   static function markDeleted($team_id) {
539         
540         // Iterate through team users and mark them as deleted.
541         $users = ttTeamHelper::getAllUsers($team_id);
542         foreach ($users as $one_user) {
543           if (!ttUserHelper::markDeleted($one_user['id']))
544                 return false;
545         }
546         
547     // Mark tasks deleted.
548     if (!ttTeamHelper::markTasksDeleted($team_id))
549       return false;
550       
551         $mdb2 = getConnection();
552         
553         // Mark projects deleted.
554     $sql = "update tt_projects set status = NULL where team_id = $team_id";
555     $affected = $mdb2->exec($sql);
556     if (is_a($affected, 'PEAR_Error'))
557       return false;
558    
559         // Mark clients deleted.
560     $sql = "update tt_clients set status = NULL where team_id = $team_id";
561         $affected = $mdb2->exec($sql);
562         if (is_a($affected, 'PEAR_Error'))
563           return false;
564
565         // Mark custom fields deleted.
566     $sql = "update tt_custom_fields set status = NULL where team_id = $team_id";
567         $affected = $mdb2->exec($sql);
568         if (is_a($affected, 'PEAR_Error'))
569           return false;
570  
571         // Mark team deleted.
572         $sql = "update tt_teams set status = NULL where id = $team_id";
573         $affected = $mdb2->exec($sql);
574         if (is_a($affected, 'PEAR_Error'))
575           return false;
576
577         return true;
578   }
579
580   // The getTeamDetails function returns team details.
581   static function getTeamDetails($team_id) {
582     $result = array();
583     $mdb2 = getConnection();
584     
585     $role_manager = ROLE_MANAGER;
586     $sql = "select t.name as team_name, u.id as manager_id, u.name as manager_name, u.login as manager_login, u.email as manager_email
587       from tt_teams t
588       inner join tt_users u on (u.team_id = t.id and u.role = $role_manager)
589       where t.id = $team_id"; 
590     
591     $res = $mdb2->query($sql);
592     if (!is_a($res, 'PEAR_Error')) {
593       $val = $res->fetchRow();
594       return $val;
595     }
596
597     return false;
598   }
599   
600   // The insert function creates a new team. 
601   static function insert($fields) {
602
603     $mdb2 = getConnection();
604     
605     $lock_spec = $fields['lock_spec'];
606     if ($lock_spec !== null) {
607       $lockspec_f = ', lock_spec';
608       $lockspec_v = ', ' . $mdb2->quote($lock_spec);
609     } else {
610       $lockspec_f = '';
611       $lockspec_v = '';
612     }
613
614     if ($fields['lock_interval'] !== null) {
615       $locktime_f = ', locktime';
616       $locktime_v = ", " . (int)$fields['lock_interval'];
617     } else {
618       $locktime_f = '';
619       $locktime_v = '';
620     }
621     
622     $lang = $fields['lang'];
623     if (!$lang) {
624       global $i18n;
625       $lang = $i18n->lang;
626     }
627
628     $decimal_mark = $fields['decimal_mark'];
629     if ($decimal_mark !== null) {
630       $decimal_mark_f = ', decimal_mark';
631       $decimal_mark_v = ', ' . $mdb2->quote($decimal_mark);
632     } else {
633       $decimal_mark_f = '';
634       $decimal_mark_v = '';     
635     }
636
637     $date_format = $fields['date_format'];
638     if ($date_format !== null) {
639       $date_format_f = ', date_format';
640       $date_format_v = ', ' . $mdb2->quote($date_format);       
641     } elseif (defined('DATE_FORMAT_DEFAULT')) {
642       $date_format_f = ', date_format';
643       $date_format_v = ', ' . $mdb2->quote(DATE_FORMAT_DEFAULT);
644     } else {
645       $date_format_f = '';
646       $date_format_v = '';      
647     }
648
649     $time_format = $fields['time_format'];
650     if ($time_format !== null) {
651       $time_format_f = ', time_format';
652       $time_format_v = ', ' . $mdb2->quote($time_format);
653     } elseif (defined('TIME_FORMAT_DEFAULT')) {
654       $time_format_f = ', time_format';
655       $time_format_v = ', ' . $mdb2->quote(TIME_FORMAT_DEFAULT);
656     } else {
657       $time_format_f = '';
658       $time_format_v = '';      
659     }
660     
661     $week_start = $fields['week_start'];
662     if ($week_start !== null) {
663       $week_start_f = ', week_start';
664       $week_start_v = ', ' . (int)$week_start;
665     } elseif (defined('WEEK_START_DEFAULT')) {
666       $week_start_f = ', week_start';
667       $week_start_v = ', ' . (int)WEEK_START_DEFAULT;           
668     } else {
669       $week_start_f = '';
670       $week_start_v = '';       
671     }
672     
673     $plugins = $fields['plugins'];
674     if ($plugins !== null) {
675       $plugins_f = ', plugins';
676       $plugins_v = ', ' . $mdb2->quote($plugins);
677     } else {
678       $plugins_f = '';
679       $plugins_v = '';          
680     }
681
682     $tracking_mode = $fields['tracking_mode'];
683     if ($tracking_mode !== null) {
684       $tracking_mode_f = ', tracking_mode';
685       $tracking_mode_v = ', ' . (int)$tracking_mode;
686     } else {
687       $tracking_mode_f = '';
688       $tracking_mode_v = '';            
689     }
690     
691     $record_type = $fields['record_type'];
692     if ($record_type !== null) {
693       $record_type_f = ', record_type';
694       $record_type_v = ', ' . (int)$record_type;
695     } else {
696       $record_type_f = '';
697       $record_type_v = '';      
698     }
699     
700     $sql = "insert into tt_teams (name, address, currency $lockspec_f $locktime_f, lang $decimal_mark_f $date_format_f $time_format_f $week_start_f $plugins_f $tracking_mode_f $record_type_f)
701       values(".
702       $mdb2->quote(trim($fields['name'])).
703       ", ".$mdb2->quote(trim($fields['address'])).
704       ", ".$mdb2->quote(trim($fields['currency']))." $lockspec_v $locktime_v, ".$mdb2->quote($lang).
705       "$decimal_mark_v $date_format_v $time_format_v $week_start_v $plugins_v $tracking_mode_v $record_type_v)";
706     $affected = $mdb2->exec($sql);
707
708     if (!is_a($affected, 'PEAR_Error')) {
709       $team_id = $mdb2->lastInsertID('tt_teams', 'id');
710       return $team_id;
711     }
712
713     return false;
714   }
715
716   // The update function updates team information.
717   static function update($team_id, $fields)    
718   {
719     // We'll require team name to be always set.
720     if (!isset($fields['name'])) return false;
721
722     $mdb2 = getConnection();
723     $name_part = 'name = '.$mdb2->quote($fields['name']);
724     $currency_part = '';
725     $addr_part = '';
726     $locktime_part = '';
727     $lang_part = '';
728     $decimal_mark_part = '';
729     $date_format_part = '';
730     $time_format_part = '';
731     $week_start_part = '';
732     $tracking_mode_part = '';
733     $record_type_part = '';
734     $plugins_part = '';
735     $lock_spec_part = '';
736     
737     if (isset($fields['address'])) $addr_part = ', address = '.$mdb2->quote($fields['address']);
738     if (isset($fields['currency'])) $currency_part = ', currency = '.$mdb2->quote($fields['currency']);
739     if (isset($fields['locktime'])) $locktime_part = ', locktime = '.intval($fields['locktime']);
740     if (isset($fields['lang'])) $lang_part = ', lang = '.$mdb2->quote($fields['lang']);
741     if (isset($fields['decimal_mark'])) $decimal_mark_part = ', decimal_mark = '.$mdb2->quote($fields['decimal_mark']);
742     if (isset($fields['date_format'])) $date_format_part = ', date_format = '.$mdb2->quote($fields['date_format']);
743     if (isset($fields['time_format'])) $time_format_part = ', time_format = '.$mdb2->quote($fields['time_format']);
744     if (isset($fields['week_start'])) $week_start_part = ', week_start = '.intval($fields['week_start']);
745     if (isset($fields['tracking_mode'])) $tracking_mode_part = ', tracking_mode = '.intval($fields['tracking_mode']);
746     if (isset($fields['record_type'])) $record_type_part = ', record_type = '.intval($fields['record_type']);
747     if (isset($fields['plugins'])) $plugins_part = ', plugins = '.$mdb2->quote($fields['plugins']);
748     if (isset($fields['lock_spec'])) $lock_spec_part = ', lock_spec = '.$mdb2->quote($fields['lock_spec']);
749
750     $sql = "update tt_teams set $name_part $addr_part $currency_part $locktime_part $lang_part $decimal_mark_part
751       $date_format_part $time_format_part $week_start_part $tracking_mode_part $record_type_part
752       $plugins_part $lock_spec_part where id = $team_id";
753     $affected = $mdb2->exec($sql);
754     
755     if (is_a($affected, 'PEAR_Error')) {
756       return false;
757     }
758     
759     return true;
760   }
761   
762   // The getInactiveTeams is a maintenance function that returns an array of inactive team ids (max 100).
763   static function getInactiveTeams() {
764     $inactive_teams = array();
765     $mdb2 = getConnection();
766
767     // Get all team ids for teams created or modified more than 1 year ago.
768     $ts = date('Y-m-d', strtotime('-1 year'));
769     $sql =  "select id from tt_teams where timestamp < '$ts' order by id";
770     $res = $mdb2->query($sql);
771
772     $count = 0;
773     if (!is_a($res, 'PEAR_Error')) {
774       while ($val = $res->fetchRow()) {
775         $team_id = $val['id'];
776         if (ttTeamHelper::isTeamActive($team_id) == false) {
777           $count ++;
778           $inactive_teams[] = $team_id;
779           // Limit the array size for perfomance by allowing this operation on small chunks only.
780           if ($count >= 25) break;
781         }
782       }
783       return $inactive_teams;
784     }
785     return false;
786   }
787   
788   // The isTeamActive determines if a team is using Time Tracker or abandoned it.
789   static function isTeamActive($team_id) {
790         $users = array();
791   
792         $mdb2 = getConnection();
793     $sql = "select id from tt_users where team_id = $team_id";
794     $res = $mdb2->query($sql);
795     if (is_a($res, 'PEAR_Error')) die($res->getMessage());
796     while ($val = $res->fetchRow()) {
797       $users[] = $val['id'];
798     }
799     $user_list = implode(',', $users); // This is a comma-separated list of user ids.
800     if (!$user_list)
801       return false; // No users in team.
802
803     $count = 0;
804         $ts = date('Y-m-d', strtotime('-2 years')); 
805     $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and timestamp > '$ts'";  
806     $res = $mdb2->query($sql);
807     if (!is_a($res, 'PEAR_Error')) {
808       if ($val = $res->fetchRow()) {
809         $count = $val['cnt'];
810       }
811     }
812
813     if ($count == 0)
814       return false;  // No time entries for the last 2 years.
815
816     if ($count <= 5) {
817       // We will consider a team inactive if it has 5 or less time entries made more than 1 year ago.
818       $count_last_year = 0;
819       $ts = date('Y-m-d', strtotime('-1 year')); 
820       $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and timestamp > '$ts'";  
821       $res = $mdb2->query($sql);
822       if (!is_a($res, 'PEAR_Error')) {
823         if ($val = $res->fetchRow()) {
824           $count_last_year = $val['cnt'];
825         }
826         if ($count_last_year == 0)
827           return false;  // No time entries for the last year and only a few entries before that...
828       } 
829     }
830     return true;
831   }
832   
833   // The delete function permanently deletes all data for a team.
834   static function delete($team_id) {
835         $mdb2 = getConnection();
836         
837         // Delete users.
838     $sql = "select id from tt_users where team_id = $team_id";
839     $res = $mdb2->query($sql);
840     if (is_a($res, 'PEAR_Error')) return false;
841     while ($val = $res->fetchRow()) {
842       $user_id = $val['id'];
843       if (!ttUserHelper::delete($user_id))
844         return false;
845     }
846
847     // Delete tasks.
848     if (!ttTeamHelper::deleteTasks($team_id))
849       return false;
850       
851     // Delete client to project binds.
852     $sql = "delete from tt_client_project_binds where client_id in (select id from tt_clients where team_id = $team_id)";
853     $affected = $mdb2->exec($sql);
854     if (is_a($affected, 'PEAR_Error'))
855       return false;
856
857     // Delete projects.
858         $sql = "delete from tt_projects where team_id = $team_id";
859         $affected = $mdb2->exec($sql);
860         if (is_a($affected, 'PEAR_Error'))
861           return false;
862
863         // Delete clients.
864         $sql = "delete from tt_clients where team_id = $team_id";
865         $affected = $mdb2->exec($sql);
866         if (is_a($affected, 'PEAR_Error'))
867           return false;
868           
869         // Delete invoices.
870         $sql = "delete from tt_invoices where team_id = $team_id";
871         $affected = $mdb2->exec($sql);
872         if (is_a($affected, 'PEAR_Error'))
873           return false;
874
875         // Delete custom fields.
876         if (!ttTeamHelper::deleteCustomFields($team_id))
877           return false;
878     
879     // Delete team.
880     $sql = "delete from tt_teams where id = $team_id";
881     $affected = $mdb2->exec($sql);
882     if (is_a($affected, 'PEAR_Error'))
883       return false;
884
885     return true;
886   }
887
888   // The markTasksDeleted deletes task binds and marks the tasks as deleted for a team.
889   static function markTasksDeleted($team_id) {
890         $mdb2 = getConnection();
891         $sql = "select id from tt_tasks where team_id = $team_id";
892         $res = $mdb2->query($sql);
893         if (is_a($res, 'PEAR_Error')) return false;
894         while ($val = $res->fetchRow()) {
895           
896           // Delete task binds.
897           $task_id = $val['id'];
898           $sql = "delete from tt_project_task_binds where task_id = $task_id";
899           $affected = $mdb2->exec($sql);
900           if (is_a($affected, 'PEAR_Error'))
901             return false;
902           
903           // Mark task as deleted.
904           $sql = "update tt_tasks set status = NULL where id = $task_id";
905           $affected = $mdb2->exec($sql);
906           if (is_a($affected, 'PEAR_Error'))
907             return false;         
908         }
909         
910         return true;
911   }
912   
913   // The deleteTasks deletes all tasks and task binds for an inactive team.
914   static function deleteTasks($team_id) {
915         $mdb2 = getConnection();
916         $sql = "select id from tt_tasks where team_id = $team_id";
917         $res = $mdb2->query($sql);
918         if (is_a($res, 'PEAR_Error')) return false;
919         while ($val = $res->fetchRow()) {
920           
921           // Delete task binds.
922           $task_id = $val['id'];
923           $sql = "delete from tt_project_task_binds where task_id = $task_id";
924           $affected = $mdb2->exec($sql);
925           if (is_a($affected, 'PEAR_Error'))
926             return false;
927           
928           // Delete task.
929           $sql = "delete from tt_tasks where id = $task_id";
930           $affected = $mdb2->exec($sql);
931           if (is_a($affected, 'PEAR_Error'))
932             return false;         
933         }
934         
935         return true;
936   }
937   
938   // The deleteCustomFields cleans up tt_custom_field_log, tt_custom_field_options and tt_custom_fields tables for an inactive team.
939   static function deleteCustomFields($team_id) {
940         $mdb2 = getConnection();
941         $sql = "select id from tt_custom_fields where team_id = $team_id";
942         $res = $mdb2->query($sql);
943         if (is_a($res, 'PEAR_Error')) return false;
944         while ($val = $res->fetchRow()) {
945           $field_id = $val['id'];
946           
947           // Clean up tt_custom_field_log.
948           $sql = "delete from tt_custom_field_log where field_id = $field_id";
949           $affected = $mdb2->exec($sql);
950           if (is_a($affected, 'PEAR_Error'))
951             return false;
952           
953           // Clean up tt_custom_field_options.
954           $sql = "delete from tt_custom_field_options where field_id = $field_id";
955           $affected = $mdb2->exec($sql);
956           if (is_a($affected, 'PEAR_Error'))
957             return false;
958           
959           // Delete custom field.
960           $sql = "delete from tt_custom_fields where id = $field_id";
961           $affected = $mdb2->exec($sql);
962           if (is_a($affected, 'PEAR_Error'))
963             return false;         
964         }
965         
966         return true;
967   }
968 }