08fa5beeecf063e49c0dfe45221e762e1c664414
[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 import('ttInvoiceHelper');
32
33 // Class ttTeamHelper - contains helper functions that operate with groups.
34 class ttTeamHelper {
35
36   // The getUsersForClient obtains all active and inactive users in a group that are relevant to a client.
37   static function getUsersForClient() {
38     global $user;
39     $mdb2 = getConnection();
40
41     $sql = "select u.id, u.name from tt_user_project_binds upb".
42       " inner join tt_client_project_binds cpb on (upb.project_id = cpb.project_id and cpb.client_id = $user->client_id)".
43       " inner join tt_users u on (u.id = upb.user_id)".
44       " where (u.status = 1 or u.status = 0)".
45       " group by u.id".
46       " order by upper(u.name)";
47     $res = $mdb2->query($sql);
48     $user_list = array();
49     if (is_a($res, 'PEAR_Error'))
50       return false;
51     while ($val = $res->fetchRow()) {
52       $user_list[] = $val;
53     }
54     return $user_list;
55   }
56
57   // The getActiveUsers obtains all active users in a given group.
58   static function getActiveUsers($options = null) {
59     global $user;
60     global $i18n;
61     $mdb2 = getConnection();
62
63     if (isset($options['getAllFields']))
64       $sql = "select u.*, r.name as role_name, r.rank from tt_users u left join tt_roles r on (u.role_id = r.id) where u.group_id = $user->group_id and u.status = 1 order by upper(u.name)";
65     else
66       $sql = "select id, name from tt_users where group_id = $user->group_id and status = 1 order by upper(name)";
67     $res = $mdb2->query($sql);
68     $user_list = array();
69     if (is_a($res, 'PEAR_Error'))
70       return false;
71     while ($val = $res->fetchRow()) {
72       // Localize top manager role name, as it is not localized in db.
73       if ($val['rank'] == 512)
74         $val['role_name'] = $i18n->get('role.top_manager.label');
75       $user_list[] = $val;
76     }
77
78     if (isset($options['putSelfFirst'])) {
79       // Put own entry at the front.
80       $cnt = count($user_list);
81       for($i = 0; $i < $cnt; $i++) {
82         if ($user_list[$i]['id'] == $user->id) {
83           $self = $user_list[$i]; // Found self.
84           array_unshift($user_list, $self); // Put own entry at the front.
85           array_splice($user_list, $i+1, 1); // Remove duplicate.
86         }
87       }
88     }
89     return $user_list;
90   }
91
92   // The swapRolesWith swaps existing user role with that of another user.
93   static function swapRolesWith($user_id) {
94     global $user;
95     $mdb2 = getConnection();
96
97     // Obtain role id for the user we are swapping ourselves with.
98     $sql = "select u.id, u.role_id from tt_users u left join tt_roles r on (u.role_id = r.id) where u.id = $user_id and u.group_id = $user->group_id and u.status = 1 and r.rank < $user->rank";
99     $res = $mdb2->query($sql);
100     if (is_a($res, 'PEAR_Error'))
101       return false;
102     $val = $res->fetchRow();
103     if (!$val['id'] || !$val['role_id'])
104       return false;
105
106     $modified_part = ', modified = now(), modified_ip = '.$mdb2->quote($_SERVER['REMOTE_ADDR']).', modified_by = '.$mdb2->quote($user->id);
107
108     // Promote user.
109     $sql = "update tt_users set role_id = $user->role_id".$modified_part." where id = $user_id and group_id = $user->group_id";
110     $affected = $mdb2->exec($sql);
111     if (is_a($affected, 'PEAR_Error')) return false;
112
113     // Demote self.
114     $role_id = $val['role_id'];
115     $sql = "update tt_users set role_id = $role_id".$modified_part." where id = $user->id and group_id = $user->group_id";
116     $affected = $mdb2->exec($sql);
117     if (is_a($affected, 'PEAR_Error')) return false;
118
119     return true;
120   }
121
122   // The getUsersForSwap obtains all users a current user can swap roles with.
123   static function getUsersForSwap() {
124     global $user;
125     $mdb2 = getConnection();
126
127     $sql = "select u.id, u.name, r.rank, r.rights from tt_users u left join tt_roles r on (u.role_id = r.id) where u.group_id = $user->group_id and u.status = 1 and r.rank < $user->rank order by upper(u.name)";
128     $res = $mdb2->query($sql);
129     $user_list = array();
130     if (is_a($res, 'PEAR_Error'))
131       return false;
132     while ($val = $res->fetchRow()) {
133       $isClient = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have track_own_time right.
134       if ($isClient)
135         continue; // Skip adding clients.
136       $user_list[] = $val;
137     }
138
139     return $user_list;
140   }
141
142   // The getUsers obtains all active and inactive (but not deleted) users in a group.
143   static function getUsers() {
144     global $user;
145     $mdb2 = getConnection();
146     $sql = "select id, name from tt_users where group_id = $user->group_id and (status = 1 or status = 0) order by upper(name)";
147     $res = $mdb2->query($sql);
148     $user_list = array();
149     if (is_a($res, 'PEAR_Error'))
150       return false;
151     while ($val = $res->fetchRow()) {
152       $user_list[] = $val;
153     }
154     return $user_list;
155   }
156
157   // The getInactiveUsers obtains all inactive users in a group.
158   static function getInactiveUsers($group_id, $all_fields = false) {
159     $mdb2 = getConnection();
160
161     if ($all_fields)
162       $sql = "select u.*, r.name as role_name from tt_users u left join tt_roles r on (u.role_id = r.id) where u.group_id = $group_id and u.status = 0 order by upper(u.name)";
163     else
164       $sql = "select id, name from tt_users where group_id = $group_id and status = 0 order by upper(name)";
165     $res = $mdb2->query($sql);
166     $result = array();
167     if (!is_a($res, 'PEAR_Error')) {
168       while ($val = $res->fetchRow()) {
169         $result[] = $val;
170       }
171       return $result;
172     }
173     return false;
174   }
175
176   // getActiveProjects - returns an array of active projects for a group.
177   static function getActiveProjects($group_id)
178   {
179     $result = array();
180     $mdb2 = getConnection();
181
182     $sql = "select id, name, description, tasks from tt_projects
183       where group_id = $group_id and status = 1 order by upper(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   // getInactiveProjects - returns an array of inactive projects for a group.
195   static function getInactiveProjects($group_id)
196   {
197     $result = array();
198     $mdb2 = getConnection();
199
200     $sql = "select id, name, description, tasks from tt_projects
201       where group_id = $group_id and status = 0 order by upper(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     }
209     return $result;
210   }
211
212   // The getAllProjects obtains all projects in a group.
213   static function getAllProjects($group_id, $all_fields = false) {
214     $mdb2 = getConnection();
215
216     if ($all_fields)
217       $sql = "select * from tt_projects where group_id = $group_id order by status, upper(name)";
218     else
219       $sql = "select id, name from tt_projects where group_id = $group_id order by status, upper(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       return $result;
227     }
228     return false;
229   }
230
231   // getActiveTasks - returns an array of active tasks for a group.
232   static function getActiveTasks($group_id)
233   {
234     $result = array();
235     $mdb2 = getConnection();
236
237     $sql = "select id, name, description from tt_tasks where group_id = $group_id and status = 1 order by upper(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   // getInactiveTasks - returns an array of inactive tasks for a group.
249   static function getInactiveTasks($group_id)
250   {
251     $result = array();
252     $mdb2 = getConnection();
253
254     $sql = "select id, name, description from tt_tasks
255       where group_id = $group_id and status = 0 order by upper(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     }
263     return $result;
264   }
265
266   // The getAllTasks obtains all tasks in a group.
267   static function getAllTasks($group_id, $all_fields = false) {
268     $mdb2 = getConnection();
269
270     if ($all_fields)
271       $sql = "select * from tt_tasks where group_id = $group_id order by status, upper(name)";
272     else
273       $sql = "select id, name from tt_tasks where group_id = $group_id order by status, upper(name)";
274     $res = $mdb2->query($sql);
275     $result = array();
276     if (!is_a($res, 'PEAR_Error')) {
277       while ($val = $res->fetchRow()) {
278         $result[] = $val;
279       }
280       return $result;
281     }
282     return false;
283   }
284
285   // getActiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
286   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
287   static function getActiveRolesForUser()
288   {
289     global $user;
290     $result = array();
291     $mdb2 = getConnection();
292
293     $sql = "select id, name, description, rank, rights from tt_roles where group_id = $user->group_id and rank < $user->rank and status = 1 order by rank";
294     $res = $mdb2->query($sql);
295     $result = array();
296     if (!is_a($res, 'PEAR_Error')) {
297       while ($val = $res->fetchRow()) {
298         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
299         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
300           continue; // Skip adding a client role.
301         $result[] = $val;
302       }
303     }
304     return $result;
305   }
306
307   // getActiveRoles - returns an array of active roles for a group.
308   static function getActiveRoles($group_id)
309   {
310     $result = array();
311     $mdb2 = getConnection();
312
313     $sql = "select id, name, description, rank, rights from tt_roles where group_id = $group_id and status = 1 order by rank";
314     $res = $mdb2->query($sql);
315     $result = array();
316     if (!is_a($res, 'PEAR_Error')) {
317       while ($val = $res->fetchRow()) {
318         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have track_own_time right.
319         $result[] = $val;
320       }
321     }
322     return $result;
323   }
324
325   // getInactiveRoles - returns an array of inactive roles for a group.
326   static function getInactiveRoles($group_id)
327   {
328     $result = array();
329     $mdb2 = getConnection();
330
331     $sql = "select id, name, rank, description from tt_roles
332       where group_id = $group_id and status = 0 order by rank";
333     $res = $mdb2->query($sql);
334     $result = array();
335     if (!is_a($res, 'PEAR_Error')) {
336       while ($val = $res->fetchRow()) {
337         $result[] = $val;
338       }
339     }
340     return $result;
341   }
342
343   // getInactiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
344   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
345   static function getInactiveRolesForUser()
346   {
347     global $user;
348     $result = array();
349     $mdb2 = getConnection();
350
351     $sql = "select id, name, description, rank, rights from tt_roles where group_id = $user->group_id and rank < $user->rank and status = 0 order by rank";
352     $res = $mdb2->query($sql);
353     $result = array();
354     if (!is_a($res, 'PEAR_Error')) {
355       while ($val = $res->fetchRow()) {
356         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
357         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
358           continue; // Skip adding a client role.
359         $result[] = $val;
360       }
361     }
362     return $result;
363   }
364
365   // The getActiveClients returns an array of active clients for a group.
366   static function getActiveClients($group_id, $all_fields = false)
367   {
368     $result = array();
369     $mdb2 = getConnection();
370
371     if ($all_fields)
372       $sql = "select * from tt_clients where group_id = $group_id and status = 1 order by upper(name)";
373     else
374       $sql = "select id, name from tt_clients where group_id = $group_id and status = 1 order by upper(name)";
375
376     $res = $mdb2->query($sql);
377     $result = array();
378     if (!is_a($res, 'PEAR_Error')) {
379       while ($val = $res->fetchRow()) {
380         $result[] = $val;
381       }
382     }
383     return $result;
384   }
385
386   // The getInactiveClients returns an array of inactive clients for a group.
387   static function getInactiveClients($group_id, $all_fields = false)
388   {
389     $result = array();
390     $mdb2 = getConnection();
391
392     if ($all_fields)
393       $sql = "select * from tt_clients where group_id = $group_id and status = 0 order by upper(name)";
394     else
395       $sql = "select id, name from tt_clients where group_id = $group_id and status = 0 order by upper(name)";
396
397     $res = $mdb2->query($sql);
398     $result = array();
399     if (!is_a($res, 'PEAR_Error')) {
400       while ($val = $res->fetchRow()) {
401         $result[] = $val;
402       }
403     }
404     return $result;
405   }
406
407   // The getAllClients obtains all clients in a group.
408   static function getAllClients($group_id, $all_fields = false) {
409     $mdb2 = getConnection();
410
411     if ($all_fields)
412       $sql = "select * from tt_clients where group_id = $group_id order by status, upper(name)";
413     else
414       $sql = "select id, name from tt_clients where group_id = $group_id order by status, upper(name)";
415
416     $res = $mdb2->query($sql);
417     $result = array();
418     if (!is_a($res, 'PEAR_Error')) {
419       while ($val = $res->fetchRow()) {
420         $result[] = $val;
421       }
422       return $result;
423     }
424     return false;
425   }
426
427   // The getActiveInvoices returns an array of active invoices for a group.
428   static function getActiveInvoices($localizeDates = true)
429   {
430     global $user;
431     $addPaidStatus = $user->isPluginEnabled('ps');
432
433     $result = array();
434     $mdb2 = getConnection();
435
436     if ($user->isClient())
437       $client_part = " and i.client_id = $user->client_id";
438
439     $sql = "select i.id, i.name, i.date, i.client_id, i.status, c.name as client_name from tt_invoices i
440       left join tt_clients c on (c.id = i.client_id)
441       where i.status = 1 and i.group_id = $user->group_id $client_part order by i.name";
442     $res = $mdb2->query($sql);
443     $result = array();
444     if (!is_a($res, 'PEAR_Error')) {
445       $dt = new DateAndTime(DB_DATEFORMAT);
446       while ($val = $res->fetchRow()) {
447         if ($localizeDates) {
448           $dt->parseVal($val['date']);
449           $val['date'] = $dt->toString($user->date_format);
450         }
451         if ($addPaidStatus)
452           $val['paid'] = ttInvoiceHelper::isPaid($val['id']);
453         $result[] = $val;
454       }
455     }
456     return $result;
457   }
458
459   // The getAllInvoices returns an array of all invoices for a group.
460   static function getAllInvoices()
461   {
462     global $user;
463
464     $result = array();
465     $mdb2 = getConnection();
466
467     $sql = "select * from tt_invoices where group_id = $user->group_id";
468     $res = $mdb2->query($sql);
469     $result = array();
470     if (!is_a($res, 'PEAR_Error')) {
471       $dt = new DateAndTime(DB_DATEFORMAT);
472       while ($val = $res->fetchRow()) {
473         $result[] = $val;
474       }
475     }
476     return $result;
477   }
478
479   // The getRecentInvoices returns an array of recent invoices (max 3) for a client.
480   static function getRecentInvoices($group_id, $client_id)
481   {
482     global $user;
483
484     $result = array();
485     $mdb2 = getConnection();
486
487     $sql = "select i.id, i.name from tt_invoices i
488       left join tt_clients c on (c.id = i.client_id)
489       where i.group_id = $group_id and i.status = 1 and c.id = $client_id
490       order by i.id desc limit 3";
491     $res = $mdb2->query($sql);
492     $result = array();
493     if (!is_a($res, 'PEAR_Error')) {
494       $dt = new DateAndTime(DB_DATEFORMAT);
495       while ($val = $res->fetchRow()) {
496         $result[] = $val;
497       }
498     }
499     return $result;
500   }
501
502   // getUserToProjectBinds - obtains all user to project binds for a group.
503   static function getUserToProjectBinds($group_id) {
504     $mdb2 = getConnection();
505
506     $result = array();
507     $sql = "select * from tt_user_project_binds where user_id in (select id from tt_users where group_id = $group_id) order by user_id, status, project_id";
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 getAllCustomFields obtains all custom fields in a group.
520   static function getAllCustomFields($group_id) {
521     $mdb2 = getConnection();
522
523     $sql = "select * from tt_custom_fields where group_id = $group_id order by status";
524
525     $res = $mdb2->query($sql);
526     $result = array();
527     if (!is_a($res, 'PEAR_Error')) {
528       while ($val = $res->fetchRow()) {
529         $result[] = $val;
530       }
531       return $result;
532     }
533     return false;
534   }
535
536   // The getAllCustomFieldOptions obtains all custom field options in a group.
537   static function getAllCustomFieldOptions($group_id) {
538     $mdb2 = getConnection();
539
540     $sql = "select * from tt_custom_field_options where field_id in (select id from tt_custom_fields where group_id = $group_id) order by id";
541
542     $res = $mdb2->query($sql);
543     $result = array();
544     if (!is_a($res, 'PEAR_Error')) {
545       while ($val = $res->fetchRow()) {
546         $result[] = $val;
547       }
548       return $result;
549     }
550     return false;
551   }
552
553   // The getCustomFieldLog obtains all custom field log entries for a group.
554   static function getCustomFieldLog($group_id) {
555     $mdb2 = getConnection();
556
557     $sql = "select * from tt_custom_field_log where field_id in (select id from tt_custom_fields where group_id = $group_id) order by id";
558
559     $res = $mdb2->query($sql);
560     $result = array();
561     if (!is_a($res, 'PEAR_Error')) {
562       while ($val = $res->fetchRow()) {
563         $result[] = $val;
564       }
565       return $result;
566     }
567     return false;
568   }
569
570   // getFavReports - obtains all favorite reports for all users in a group.
571   static function getFavReports($group_id) {
572     $mdb2 = getConnection();
573
574     $result = array();
575     $sql = "select * from tt_fav_reports where user_id in (select id from tt_users where group_id = $group_id)";
576     $res = $mdb2->query($sql);
577     $result = array();
578     if (!is_a($res, 'PEAR_Error')) {
579       while ($val = $res->fetchRow()) {
580         $result[] = $val;
581       }
582       return $result;
583     }
584     return false;
585   }
586
587   // getExpenseItems - obtains all expense items for all users in a group.
588   static function getExpenseItems($group_id) {
589     $mdb2 = getConnection();
590
591     $result = array();
592     $sql = "select * from tt_expense_items where user_id in (select id from tt_users where group_id = $group_id)";
593     $res = $mdb2->query($sql);
594     $result = array();
595     if (!is_a($res, 'PEAR_Error')) {
596       while ($val = $res->fetchRow()) {
597         $result[] = $val;
598       }
599       return $result;
600     }
601     return false;
602   }
603
604   // getPredefinedExpenses - obtains predefined expenses for a group.
605   static function getPredefinedExpenses($group_id) {
606     global $user;
607     $replaceDecimalMark = ('.' != $user->decimal_mark);
608
609     $mdb2 = getConnection();
610
611     $result = array();
612     $sql = "select id, name, cost from tt_predefined_expenses where group_id = $group_id";
613     $res = $mdb2->query($sql);
614     $result = array();
615     if (!is_a($res, 'PEAR_Error')) {
616       while ($val = $res->fetchRow()) {
617         if ($replaceDecimalMark)
618           $val['cost'] = str_replace('.', $user->decimal_mark, $val['cost']);
619         $result[] = $val;
620       }
621       return $result;
622     }
623     return false;
624   }
625
626   // getNotifications - obtains notification descriptions for a group.
627   static function getNotifications($group_id) {
628     $mdb2 = getConnection();
629
630     $result = array();
631     $sql = "select c.id, c.cron_spec, c.email, c.report_condition, fr.name from tt_cron c
632       left join tt_fav_reports fr on (fr.id = c.report_id)
633       where c.group_id = $group_id and c.status = 1 and fr.status = 1";
634     $res = $mdb2->query($sql);
635     $result = array();
636     if (!is_a($res, 'PEAR_Error')) {
637       while ($val = $res->fetchRow()) {
638         $result[] = $val;
639       }
640       return $result;
641     }
642     return false;
643   }
644
645   // getMonthlyQuotas - obtains monthly quotas for a group.
646   static function getMonthlyQuotas($group_id) {
647     $mdb2 = getConnection();
648
649     $result = array();
650     $sql = "select year, month, minutes from tt_monthly_quotas where group_id = $group_id";
651     $res = $mdb2->query($sql);
652     $result = array();
653     if (!is_a($res, 'PEAR_Error')) {
654       while ($val = $res->fetchRow()) {
655         $result[] = $val;
656       }
657       return $result;
658     }
659     return false;
660   }
661
662   // The getInactiveGroups is a maintenance function that returns an array of inactive group ids (max 100).
663   static function getInactiveGroups() {
664     $inactive_groups = array();
665     $mdb2 = getConnection();
666
667     // Get all group ids for groups created or modified more than 8 months ago.
668     // $ts = date('Y-m-d', strtotime('-1 year'));
669     $ts = $mdb2->quote(date('Y-m-d', strtotime('-8 month')));
670     $sql =  "select id from tt_groups where created < $ts and (modified is null or modified < $ts) order by id";
671     $res = $mdb2->query($sql);
672
673     $count = 0;
674     if (!is_a($res, 'PEAR_Error')) {
675       while ($val = $res->fetchRow()) {
676         $group_id = $val['id'];
677         if (ttTeamHelper::isGroupActive($group_id) == false) {
678           $count++;
679           $inactive_groups[] = $group_id;
680           // Limit the array size for perfomance by allowing this operation on small chunks only.
681           if ($count >= 100) break;
682         }
683       }
684       return $inactive_groups;
685     }
686     return false;
687   }
688
689   // The isGroupActive determines if a group is using Time Tracker or abandoned it.
690   static function isGroupActive($group_id) {
691     $users = array();
692
693     $mdb2 = getConnection();
694     $sql = "select id from tt_users where group_id = $group_id";
695     $res = $mdb2->query($sql);
696     if (is_a($res, 'PEAR_Error')) die($res->getMessage());
697     while ($val = $res->fetchRow()) {
698       $users[] = $val['id'];
699     }
700     $user_list = implode(',', $users); // This is a comma-separated list of user ids.
701     if (!$user_list)
702       return false; // No users in group.
703
704     $count = 0;
705     $ts = date('Y-m-d', strtotime('-2 years'));
706     $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and created > '$ts'";
707     $res = $mdb2->query($sql);
708     if (!is_a($res, 'PEAR_Error')) {
709       if ($val = $res->fetchRow()) {
710         $count = $val['cnt'];
711       }
712     }
713
714     if ($count == 0)
715       return false;  // No time entries for the last 2 years.
716
717     if ($count <= 5) {
718       // We will consider a group inactive if it has 5 or less time entries made more than 1 year ago.
719       $count_last_year = 0;
720       $ts = date('Y-m-d', strtotime('-1 year'));
721       $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and created > '$ts'";
722       $res = $mdb2->query($sql);
723       if (!is_a($res, 'PEAR_Error')) {
724         if ($val = $res->fetchRow()) {
725           $count_last_year = $val['cnt'];
726         }
727         if ($count_last_year == 0)
728           return false;  // No time entries for the last year and only a few entries before that.
729       }
730     }
731     return true;
732   }
733
734   // The delete function permanently deletes all data for a group.
735   static function delete($group_id) {
736     $mdb2 = getConnection();
737
738     // Delete users.
739     $sql = "select id from tt_users where group_id = $group_id";
740     $res = $mdb2->query($sql);
741     if (is_a($res, 'PEAR_Error')) return false;
742     while ($val = $res->fetchRow()) {
743       $user_id = $val['id'];
744       if (!ttUserHelper::delete($user_id)) return false;
745     }
746
747     // Delete tasks.
748     if (!ttTeamHelper::deleteTasks($group_id)) return false;
749
750     // Delete client to project binds.
751     $sql = "delete from tt_client_project_binds where client_id in (select id from tt_clients where group_id = $group_id)";
752     $affected = $mdb2->exec($sql);
753     if (is_a($affected, 'PEAR_Error')) return false;
754
755     // Delete projects.
756     $sql = "delete from tt_projects where group_id = $group_id";
757     $affected = $mdb2->exec($sql);
758     if (is_a($affected, 'PEAR_Error')) return false;
759
760     // Delete clients.
761     $sql = "delete from tt_clients where group_id = $group_id";
762     $affected = $mdb2->exec($sql);
763     if (is_a($affected, 'PEAR_Error')) return false;
764
765     // Delete invoices.
766     $sql = "delete from tt_invoices where group_id = $group_id";
767     $affected = $mdb2->exec($sql);
768     if (is_a($affected, 'PEAR_Error')) return false;
769
770     // Delete custom fields.
771     if (!ttTeamHelper::deleteCustomFields($group_id)) return false;
772
773     // Delete roles.
774     $sql = "delete from tt_roles where group_id = $group_id";
775     $affected = $mdb2->exec($sql);
776     if (is_a($affected, 'PEAR_Error')) return false;
777
778     // Delete group.
779     $sql = "delete from tt_groups where id = $group_id";
780     $affected = $mdb2->exec($sql);
781     if (is_a($affected, 'PEAR_Error')) return false;
782
783     return true;
784   }
785
786   // The deleteTasks deletes all tasks and task binds for an inactive group.
787   static function deleteTasks($group_id) {
788     $mdb2 = getConnection();
789     $sql = "select id from tt_tasks where group_id = $group_id";
790     $res = $mdb2->query($sql);
791     if (is_a($res, 'PEAR_Error')) return false;
792
793     while ($val = $res->fetchRow()) {
794
795       // Delete task binds.
796       $task_id = $val['id'];
797       $sql = "delete from tt_project_task_binds where task_id = $task_id";
798       $affected = $mdb2->exec($sql);
799       if (is_a($affected, 'PEAR_Error')) return false;
800
801       // Delete task.
802       $sql = "delete from tt_tasks where id = $task_id";
803       $affected = $mdb2->exec($sql);
804       if (is_a($affected, 'PEAR_Error')) return false;
805     }
806
807     return true;
808   }
809
810   // The deleteCustomFields cleans up tt_custom_field_log, tt_custom_field_options and tt_custom_fields tables for an inactive group.
811   static function deleteCustomFields($group_id) {
812     $mdb2 = getConnection();
813     $sql = "select id from tt_custom_fields where group_id = $group_id";
814     $res = $mdb2->query($sql);
815     if (is_a($res, 'PEAR_Error')) return false;
816
817     while ($val = $res->fetchRow()) {
818       $field_id = $val['id'];
819
820       // Clean up tt_custom_field_log.
821       $sql = "delete from tt_custom_field_log where field_id = $field_id";
822       $affected = $mdb2->exec($sql);
823       if (is_a($affected, 'PEAR_Error')) return false;
824
825       // Clean up tt_custom_field_options.
826       $sql = "delete from tt_custom_field_options where field_id = $field_id";
827       $affected = $mdb2->exec($sql);
828       if (is_a($affected, 'PEAR_Error')) return false;
829
830       // Delete custom field.
831       $sql = "delete from tt_custom_fields where id = $field_id";
832       $affected = $mdb2->exec($sql);
833       if (is_a($affected, 'PEAR_Error')) return false;
834     }
835
836     return true;
837   }
838 }