8cc9660ba5c262739a3ad6262ccf6af6166bf826
[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     if ($fields['lock_interval'] !== null) {
606       $locktime_f = ', locktime';
607       $locktime_v = ", " . (int)$fields['lock_interval'];
608     } else {
609       $locktime_f = '';
610       $locktime_v = '';
611     }
612     
613     $lang = $fields['lang'];
614     if (!$lang) {
615       global $i18n;
616       $lang = $i18n->lang;
617     }
618     
619     $decimal_mark = $fields['decimal_mark'];
620     if ($decimal_mark !== null) {
621       $decimal_mark_f = ', decimal_mark';
622       $decimal_mark_v = ', ' . $mdb2->quote($decimal_mark);     
623     } else {
624       $decimal_mark_f = '';
625       $decimal_mark_v = '';     
626     }
627
628     $date_format = $fields['date_format'];
629     if ($date_format !== null) {
630       $date_format_f = ', date_format';
631       $date_format_v = ', ' . $mdb2->quote($date_format);       
632     } elseif (defined('DATE_FORMAT_DEFAULT')) {
633       $date_format_f = ', date_format';
634       $date_format_v = ', ' . $mdb2->quote(DATE_FORMAT_DEFAULT);
635     } else {
636       $date_format_f = '';
637       $date_format_v = '';      
638     }
639
640     $time_format = $fields['time_format'];
641     if ($time_format !== null) {
642       $time_format_f = ', time_format';
643       $time_format_v = ', ' . $mdb2->quote($time_format);
644     } elseif (defined('TIME_FORMAT_DEFAULT')) {
645       $time_format_f = ', time_format';
646       $time_format_v = ', ' . $mdb2->quote(TIME_FORMAT_DEFAULT);
647     } else {
648       $time_format_f = '';
649       $time_format_v = '';      
650     }
651     
652     $week_start = $fields['week_start'];
653     if ($week_start !== null) {
654       $week_start_f = ', week_start';
655       $week_start_v = ', ' . (int)$week_start;
656     } elseif (defined('WEEK_START_DEFAULT')) {
657       $week_start_f = ', week_start';
658       $week_start_v = ', ' . (int)WEEK_START_DEFAULT;           
659     } else {
660       $week_start_f = '';
661       $week_start_v = '';       
662     }
663     
664     $plugins = $fields['plugins'];
665     if ($plugins !== null) {
666       $plugins_f = ', plugins';
667       $plugins_v = ', ' . $mdb2->quote($plugins);
668     } else {
669       $plugins_f = '';
670       $plugins_v = '';          
671     }
672
673     $tracking_mode = $fields['tracking_mode'];
674     if ($tracking_mode !== null) {
675       $tracking_mode_f = ', tracking_mode';
676       $tracking_mode_v = ', ' . (int)$tracking_mode;
677     } else {
678       $tracking_mode_f = '';
679       $tracking_mode_v = '';            
680     }
681     
682     $record_type = $fields['record_type'];
683     if ($record_type !== null) {
684       $record_type_f = ', record_type';
685       $record_type_v = ', ' . (int)$record_type;
686     } else {
687       $record_type_f = '';
688       $record_type_v = '';      
689     }
690     
691     $sql = "insert into tt_teams (name, address, currency $locktime_f, lang $decimal_mark_f $date_format_f $time_format_f $week_start_f $plugins_f $tracking_mode_f $record_type_f)
692       values(".
693       $mdb2->quote(trim($fields['name'])).
694       ", ".$mdb2->quote(trim($fields['address'])).
695       ", ".$mdb2->quote(trim($fields['currency']))." $locktime_v, ".$mdb2->quote($lang).
696       "$decimal_mark_v $date_format_v $time_format_v $week_start_v $plugins_v $tracking_mode_v $record_type_v)";
697     $affected = $mdb2->exec($sql);
698
699     if (!is_a($affected, 'PEAR_Error')) {
700       $team_id = $mdb2->lastInsertID('tt_teams', 'id');
701       return $team_id;
702     }
703
704     return false;
705   }
706
707   // The update function updates team information.
708   static function update($team_id, $fields)    
709   {
710     // We'll require team name to be always set.
711     if (!isset($fields['name'])) return false;
712
713     $mdb2 = getConnection();
714     $name_part = 'name = '.$mdb2->quote($fields['name']);
715     $currency_part = '';
716     $addr_part = '';
717     $locktime_part = '';
718     $lang_part = '';
719     $decimal_mark_part = '';
720     $date_format_part = '';
721     $time_format_part = '';
722     $week_start_part = '';
723     $tracking_mode_part = '';
724     $record_type_part = '';
725     $plugins_part = '';
726     $lock_spec_part = '';
727     
728     if (isset($fields['address'])) $addr_part = ', address = '.$mdb2->quote($fields['address']);
729     if (isset($fields['currency'])) $currency_part = ', currency = '.$mdb2->quote($fields['currency']);
730     if (isset($fields['locktime'])) $locktime_part = ', locktime = '.intval($fields['locktime']);
731     if (isset($fields['lang'])) $lang_part = ', lang = '.$mdb2->quote($fields['lang']);
732     if (isset($fields['decimal_mark'])) $decimal_mark_part = ', decimal_mark = '.$mdb2->quote($fields['decimal_mark']);
733     if (isset($fields['date_format'])) $date_format_part = ', date_format = '.$mdb2->quote($fields['date_format']);
734     if (isset($fields['time_format'])) $time_format_part = ', time_format = '.$mdb2->quote($fields['time_format']);
735     if (isset($fields['week_start'])) $week_start_part = ', week_start = '.intval($fields['week_start']);
736     if (isset($fields['tracking_mode'])) $tracking_mode_part = ', tracking_mode = '.intval($fields['tracking_mode']);
737     if (isset($fields['record_type'])) $record_type_part = ', record_type = '.intval($fields['record_type']);
738     if (isset($fields['plugins'])) $plugins_part = ', plugins = '.$mdb2->quote($fields['plugins']);
739     if (isset($fields['lock_spec'])) $lock_spec_part = ', lock_spec = '.$mdb2->quote($fields['lock_spec']);
740
741     $sql = "update tt_teams set $name_part $addr_part $currency_part $locktime_part $lang_part $decimal_mark_part
742       $date_format_part $time_format_part $week_start_part $tracking_mode_part $record_type_part
743       $plugins_part $lock_spec_part where id = $team_id";
744     $affected = $mdb2->exec($sql);
745     
746     if (is_a($affected, 'PEAR_Error')) {
747       return false;
748     }
749     
750     return true;
751   }
752   
753   // The getInactiveTeams is a maintenance function that returns an array of inactive team ids (max 100).
754   static function getInactiveTeams() {
755     $inactive_teams = array();
756     $mdb2 = getConnection();
757
758     // Get all team ids for teams created or modified more than 1 year ago.
759     $ts = date('Y-m-d', strtotime('-1 year'));
760     $sql =  "select id from tt_teams where timestamp < '$ts' order by id";
761     $res = $mdb2->query($sql);
762
763     $count = 0;
764     if (!is_a($res, 'PEAR_Error')) {
765       while ($val = $res->fetchRow()) {
766         $team_id = $val['id'];
767         if (ttTeamHelper::isTeamActive($team_id) == false) {
768           $count ++;
769           $inactive_teams[] = $team_id;
770           // Limit the array size for perfomance by allowing this operation on small chunks only.
771           if ($count >= 25) break;
772         }
773       }
774       return $inactive_teams;
775     }
776     return false;
777   }
778   
779   // The isTeamActive determines if a team is using Time Tracker or abandoned it.
780   static function isTeamActive($team_id) {
781         $users = array();
782   
783         $mdb2 = getConnection();
784     $sql = "select id from tt_users where team_id = $team_id";
785     $res = $mdb2->query($sql);
786     if (is_a($res, 'PEAR_Error')) die($res->getMessage());
787     while ($val = $res->fetchRow()) {
788       $users[] = $val['id'];
789     }
790     $user_list = implode(',', $users); // This is a comma-separated list of user ids.
791     if (!$user_list)
792       return false; // No users in team.
793
794     $count = 0;
795         $ts = date('Y-m-d', strtotime('-2 years')); 
796     $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and timestamp > '$ts'";  
797     $res = $mdb2->query($sql);
798     if (!is_a($res, 'PEAR_Error')) {
799       if ($val = $res->fetchRow()) {
800         $count = $val['cnt'];
801       }
802     }
803
804     if ($count == 0)
805       return false;  // No time entries for the last 2 years.
806
807     if ($count <= 5) {
808       // We will consider a team inactive if it has 5 or less time entries made more than 1 year ago.
809       $count_last_year = 0;
810       $ts = date('Y-m-d', strtotime('-1 year')); 
811       $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and timestamp > '$ts'";  
812       $res = $mdb2->query($sql);
813       if (!is_a($res, 'PEAR_Error')) {
814         if ($val = $res->fetchRow()) {
815           $count_last_year = $val['cnt'];
816         }
817         if ($count_last_year == 0)
818           return false;  // No time entries for the last year and only a few entries before that...
819       } 
820     }
821     return true;
822   }
823   
824   // The delete function permanently deletes all data for a team.
825   static function delete($team_id) {
826         $mdb2 = getConnection();
827         
828         // Delete users.
829     $sql = "select id from tt_users where team_id = $team_id";
830     $res = $mdb2->query($sql);
831     if (is_a($res, 'PEAR_Error')) return false;
832     while ($val = $res->fetchRow()) {
833       $user_id = $val['id'];
834       if (!ttUserHelper::delete($user_id))
835         return false;
836     }
837
838     // Delete tasks.
839     if (!ttTeamHelper::deleteTasks($team_id))
840       return false;
841       
842     // Delete client to project binds.
843     $sql = "delete from tt_client_project_binds where client_id in (select id from tt_clients where team_id = $team_id)";
844     $affected = $mdb2->exec($sql);
845     if (is_a($affected, 'PEAR_Error'))
846       return false;
847
848     // Delete projects.
849         $sql = "delete from tt_projects where team_id = $team_id";
850         $affected = $mdb2->exec($sql);
851         if (is_a($affected, 'PEAR_Error'))
852           return false;
853
854         // Delete clients.
855         $sql = "delete from tt_clients where team_id = $team_id";
856         $affected = $mdb2->exec($sql);
857         if (is_a($affected, 'PEAR_Error'))
858           return false;
859           
860         // Delete invoices.
861         $sql = "delete from tt_invoices where team_id = $team_id";
862         $affected = $mdb2->exec($sql);
863         if (is_a($affected, 'PEAR_Error'))
864           return false;
865
866         // Delete custom fields.
867         if (!ttTeamHelper::deleteCustomFields($team_id))
868           return false;
869     
870     // Delete team.
871     $sql = "delete from tt_teams where id = $team_id";
872     $affected = $mdb2->exec($sql);
873     if (is_a($affected, 'PEAR_Error'))
874       return false;
875
876     return true;
877   }
878
879   // The markTasksDeleted deletes task binds and marks the tasks as deleted for a team.
880   static function markTasksDeleted($team_id) {
881         $mdb2 = getConnection();
882         $sql = "select id from tt_tasks where team_id = $team_id";
883         $res = $mdb2->query($sql);
884         if (is_a($res, 'PEAR_Error')) return false;
885         while ($val = $res->fetchRow()) {
886           
887           // Delete task binds.
888           $task_id = $val['id'];
889           $sql = "delete from tt_project_task_binds where task_id = $task_id";
890           $affected = $mdb2->exec($sql);
891           if (is_a($affected, 'PEAR_Error'))
892             return false;
893           
894           // Mark task as deleted.
895           $sql = "update tt_tasks set status = NULL where id = $task_id";
896           $affected = $mdb2->exec($sql);
897           if (is_a($affected, 'PEAR_Error'))
898             return false;         
899         }
900         
901         return true;
902   }
903   
904   // The deleteTasks deletes all tasks and task binds for an inactive team.
905   static function deleteTasks($team_id) {
906         $mdb2 = getConnection();
907         $sql = "select id from tt_tasks where team_id = $team_id";
908         $res = $mdb2->query($sql);
909         if (is_a($res, 'PEAR_Error')) return false;
910         while ($val = $res->fetchRow()) {
911           
912           // Delete task binds.
913           $task_id = $val['id'];
914           $sql = "delete from tt_project_task_binds where task_id = $task_id";
915           $affected = $mdb2->exec($sql);
916           if (is_a($affected, 'PEAR_Error'))
917             return false;
918           
919           // Delete task.
920           $sql = "delete from tt_tasks where id = $task_id";
921           $affected = $mdb2->exec($sql);
922           if (is_a($affected, 'PEAR_Error'))
923             return false;         
924         }
925         
926         return true;
927   }
928   
929   // The deleteCustomFields cleans up tt_custom_field_log, tt_custom_field_options and tt_custom_fields tables for an inactive team.
930   static function deleteCustomFields($team_id) {
931         $mdb2 = getConnection();
932         $sql = "select id from tt_custom_fields where team_id = $team_id";
933         $res = $mdb2->query($sql);
934         if (is_a($res, 'PEAR_Error')) return false;
935         while ($val = $res->fetchRow()) {
936           $field_id = $val['id'];
937           
938           // Clean up tt_custom_field_log.
939           $sql = "delete from tt_custom_field_log where field_id = $field_id";
940           $affected = $mdb2->exec($sql);
941           if (is_a($affected, 'PEAR_Error'))
942             return false;
943           
944           // Clean up tt_custom_field_options.
945           $sql = "delete from tt_custom_field_options where field_id = $field_id";
946           $affected = $mdb2->exec($sql);
947           if (is_a($affected, 'PEAR_Error'))
948             return false;
949           
950           // Delete custom field.
951           $sql = "delete from tt_custom_fields where id = $field_id";
952           $affected = $mdb2->exec($sql);
953           if (is_a($affected, 'PEAR_Error'))
954             return false;         
955         }
956         
957         return true;
958   }
959 }