de034794f38fd2ef6c6cdcd88a0ba2fce8730de8
[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 teams.
34 class ttTeamHelper {
35
36   // The getUserCount function returns number of people in team.
37   static function getUserCount($team_id) {
38     $mdb2 = getConnection();
39
40     $sql = "select count(id) as cnt from tt_users where team_id = $team_id and status = 1";
41     $res = $mdb2->query($sql);
42
43     if (!is_a($res, 'PEAR_Error')) {
44       $val = $res->fetchRow();
45       return $val['cnt'];
46     }
47     return false;
48   }
49
50   // The getUsersForClient obtains all active and inactive users in a team that are relevant to a client.
51   static function getUsersForClient() {
52     global $user;
53     $mdb2 = getConnection();
54
55     $sql = "select u.id, u.name from tt_user_project_binds upb
56       inner join tt_client_project_binds cpb on (upb.project_id = cpb.project_id and cpb.client_id = $user->client_id)
57       inner join tt_users u on (u.id = upb.user_id)
58       where (u.status = 1 or u.status = 0)
59       group by u.id
60       order by upper(u.name)";
61     $res = $mdb2->query($sql);
62     $user_list = array();
63     if (is_a($res, 'PEAR_Error'))
64       return false;
65     while ($val = $res->fetchRow()) {
66       $user_list[] = $val;
67     }
68     return $user_list;
69   }
70
71   // The getActiveUsers obtains all active users in a given team.
72   static function getActiveUsers($options = null) {
73     global $user;
74     global $i18n;
75     $mdb2 = getConnection();
76
77     if (isset($options['getAllFields']))
78       $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.team_id = $user->team_id and u.status = 1 order by upper(u.name)";
79     else
80       $sql = "select id, name from tt_users where team_id = $user->team_id and status = 1 order by upper(name)";
81     $res = $mdb2->query($sql);
82     $user_list = array();
83     if (is_a($res, 'PEAR_Error'))
84       return false;
85     while ($val = $res->fetchRow()) {
86       // Localize top manager role name, as it is not localized in db.
87       if ($val['rank'] == 512)
88         $val['role_name'] = $i18n->get('role.top_manager.label');
89       $user_list[] = $val;
90     }
91
92     if (isset($options['putSelfFirst'])) {
93       // Put own entry at the front.
94       $cnt = count($user_list);
95       for($i = 0; $i < $cnt; $i++) {
96         if ($user_list[$i]['id'] == $user->id) {
97           $self = $user_list[$i]; // Found self.
98           array_unshift($user_list, $self); // Put own entry at the front.
99           array_splice($user_list, $i+1, 1); // Remove duplicate.
100         }
101       }
102     }
103     return $user_list;
104   }
105
106   // The swapRolesWith swaps existing user role with that of another user.
107   static function swapRolesWith($user_id) {
108     global $user;
109     $mdb2 = getConnection();
110
111     $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.team_id = $user->team_id and u.status = 1 and r.rank < $user->rank";
112     $res = $mdb2->query($sql);
113     if (is_a($res, 'PEAR_Error'))
114       return false;
115     $val = $res->fetchRow();
116     if (!$val['id'] || !$val['role_id'])
117       return false;
118
119     $modified_part = ', modified = now(), modified_ip = '.$mdb2->quote($_SERVER['REMOTE_ADDR']).', modified_by = '.$mdb2->quote($user->id);
120
121     // Promote user.
122     $sql = "update tt_users set role_id = $user->role_id".$modified_part." where id = $user_id and team_id = $user->team_id";
123     $affected = $mdb2->exec($sql);
124     if (is_a($affected, 'PEAR_Error')) return false;
125
126     // Demote self.
127     $role_id = $val['role_id'];
128     $sql = "update tt_users set role_id = $role_id".$modified_part." where id = $user->id and team_id = $user->team_id";
129     $affected = $mdb2->exec($sql);
130     if (is_a($affected, 'PEAR_Error')) return false;
131
132     return true;
133   }
134
135   // The getUsersForSwap obtains all users a current user can swap roles with.
136   static function getUsersForSwap() {
137     global $user;
138     $mdb2 = getConnection();
139
140     $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.team_id = $user->team_id and u.status = 1 and r.rank < $user->rank order by upper(u.name)";
141     $res = $mdb2->query($sql);
142     $user_list = array();
143     if (is_a($res, 'PEAR_Error'))
144       return false;
145     while ($val = $res->fetchRow()) {
146       $isClient = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
147       if ($isClient)
148         continue; // Skip adding clients.
149       $user_list[] = $val;
150     }
151
152     return $user_list;
153   }
154
155     // The getUsers obtains all active and inactive (but not deleted) users in a given team.
156   static function getUsers() {
157     global $user;
158     $mdb2 = getConnection();
159     $sql = "select id, name from tt_users where team_id = $user->team_id and (status = 1 or status = 0) order by upper(name)";
160     $res = $mdb2->query($sql);
161     $user_list = array();
162     if (is_a($res, 'PEAR_Error'))
163       return false;
164     while ($val = $res->fetchRow()) {
165       $user_list[] = $val;
166     }
167     return $user_list;
168   }
169
170   // The getInactiveUsers obtains all inactive users in a given team.
171   static function getInactiveUsers($team_id, $all_fields = false) {
172     $mdb2 = getConnection();
173
174     if ($all_fields)
175       $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.team_id = $team_id and u.status = 0 order by upper(u.name)";
176     else
177       $sql = "select id, name from tt_users where team_id = $team_id and status = 0 order by upper(name)";
178     $res = $mdb2->query($sql);
179     $result = array();
180     if (!is_a($res, 'PEAR_Error')) {
181       while ($val = $res->fetchRow()) {
182         $result[] = $val;
183       }
184       return $result;
185     }
186     return false;
187   }
188
189   // The getAllUsers obtains all users in a given team.
190   static function getAllUsers($team_id, $all_fields = false) {
191     $mdb2 = getConnection();
192     if ($all_fields)
193       $sql = "select * from tt_users where team_id = $team_id order by upper(name)";
194     else
195       $sql = "select id, name from tt_users where team_id = $team_id order by upper(name)";
196     $res = $mdb2->query($sql);
197     $result = array();
198     if (!is_a($res, 'PEAR_Error')) {
199       while ($val = $res->fetchRow()) {
200         $result[] = $val;
201       }
202       return $result;
203     }
204     return false;
205   }
206
207   // getActiveProjects - returns an array of active projects for team.
208   static function getActiveProjects($team_id)
209   {
210     $result = array();
211     $mdb2 = getConnection();
212
213     $sql = "select id, name, description, tasks from tt_projects
214       where team_id = $team_id and status = 1 order by upper(name)";
215     $res = $mdb2->query($sql);
216     $result = array();
217     if (!is_a($res, 'PEAR_Error')) {
218       while ($val = $res->fetchRow()) {
219         $result[] = $val;
220       }
221     }
222     return $result;
223   }
224
225   // getInactiveProjects - returns an array of inactive projects for team.
226   static function getInactiveProjects($team_id)
227   {
228     $result = array();
229     $mdb2 = getConnection();
230
231     $sql = "select id, name, description, tasks from tt_projects
232       where team_id = $team_id and status = 0 order by upper(name)";
233     $res = $mdb2->query($sql);
234     $result = array();
235     if (!is_a($res, 'PEAR_Error')) {
236       while ($val = $res->fetchRow()) {
237         $result[] = $val;
238       }
239     }
240     return $result;
241   }
242
243   // The getAllProjects obtains all projects in a given team.
244   static function getAllProjects($team_id, $all_fields = false) {
245     $mdb2 = getConnection();
246
247     if ($all_fields)
248       $sql = "select * from tt_projects where team_id = $team_id order by status, upper(name)";
249     else
250       $sql = "select id, name from tt_projects where team_id = $team_id order by status, upper(name)";
251     $res = $mdb2->query($sql);
252     $result = array();
253     if (!is_a($res, 'PEAR_Error')) {
254       while ($val = $res->fetchRow()) {
255         $result[] = $val;
256       }
257       return $result;
258     }
259     return false;
260   }
261
262   // getActiveTasks - returns an array of active tasks for team.
263   static function getActiveTasks($team_id)
264   {
265     $result = array();
266     $mdb2 = getConnection();
267
268     $sql = "select id, name, description from tt_tasks where team_id = $team_id and status = 1 order by upper(name)";
269     $res = $mdb2->query($sql);
270     $result = array();
271     if (!is_a($res, 'PEAR_Error')) {
272       while ($val = $res->fetchRow()) {
273         $result[] = $val;
274       }
275     }
276     return $result;
277   }
278
279   // getInactiveTasks - returns an array of inactive tasks for team.
280   static function getInactiveTasks($team_id)
281   {
282     $result = array();
283     $mdb2 = getConnection();
284
285     $sql = "select id, name, description from tt_tasks
286       where team_id = $team_id and status = 0 order by upper(name)";
287     $res = $mdb2->query($sql);
288     $result = array();
289     if (!is_a($res, 'PEAR_Error')) {
290       while ($val = $res->fetchRow()) {
291         $result[] = $val;
292       }
293     }
294     return $result;
295   }
296
297   // The getAllTasks obtains all tasks in a given team.
298   static function getAllTasks($team_id, $all_fields = false) {
299     $mdb2 = getConnection();
300
301     if ($all_fields)
302       $sql = "select * from tt_tasks where team_id = $team_id order by status, upper(name)";
303     else
304       $sql = "select id, name from tt_tasks where team_id = $team_id order by status, upper(name)";
305     $res = $mdb2->query($sql);
306     $result = array();
307     if (!is_a($res, 'PEAR_Error')) {
308       while ($val = $res->fetchRow()) {
309         $result[] = $val;
310       }
311       return $result;
312     }
313     return false;
314   }
315
316   // getActiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
317   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
318   static function getActiveRolesForUser()
319   {
320     global $user;
321     $result = array();
322     $mdb2 = getConnection();
323
324     $sql = "select id, name, description, rank, rights from tt_roles where team_id = $user->team_id and rank < $user->rank and status = 1 order by rank";
325     $res = $mdb2->query($sql);
326     $result = array();
327     if (!is_a($res, 'PEAR_Error')) {
328       while ($val = $res->fetchRow()) {
329         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
330         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
331           continue; // Skip adding a client role.
332         $result[] = $val;
333       }
334     }
335     return $result;
336   }
337
338   // getActiveRoles - returns an array of active roles for team.
339   static function getActiveRoles($team_id)
340   {
341     $result = array();
342     $mdb2 = getConnection();
343
344     $sql = "select id, name, description, rank, rights from tt_roles where team_id = $team_id and status = 1 order by rank";
345     $res = $mdb2->query($sql);
346     $result = array();
347     if (!is_a($res, 'PEAR_Error')) {
348       while ($val = $res->fetchRow()) {
349         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
350         $result[] = $val;
351       }
352     }
353     return $result;
354   }
355
356   // getInactiveRoles - returns an array of inactive roles for team.
357   static function getInactiveRoles($team_id)
358   {
359     $result = array();
360     $mdb2 = getConnection();
361
362     $sql = "select id, name, rank, description from tt_roles
363       where team_id = $team_id and status = 0 order by rank";
364     $res = $mdb2->query($sql);
365     $result = array();
366     if (!is_a($res, 'PEAR_Error')) {
367       while ($val = $res->fetchRow()) {
368         $result[] = $val;
369       }
370     }
371     return $result;
372   }
373
374   // getInactiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
375   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
376   static function getInactiveRolesForUser()
377   {
378     global $user;
379     $result = array();
380     $mdb2 = getConnection();
381
382     $sql = "select id, name, description, rank, rights from tt_roles where team_id = $user->team_id and rank < $user->rank and status = 0 order by rank";
383     $res = $mdb2->query($sql);
384     $result = array();
385     if (!is_a($res, 'PEAR_Error')) {
386       while ($val = $res->fetchRow()) {
387         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
388         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
389           continue; // Skip adding a client role.
390         $result[] = $val;
391       }
392     }
393     return $result;
394   }
395
396   // The getActiveClients returns an array of active clients for team.
397   static function getActiveClients($team_id, $all_fields = false)
398   {
399     $result = array();
400     $mdb2 = getConnection();
401
402     if ($all_fields)
403       $sql = "select * from tt_clients where team_id = $team_id and status = 1 order by upper(name)";
404     else
405       $sql = "select id, name from tt_clients where team_id = $team_id and status = 1 order by upper(name)";
406
407     $res = $mdb2->query($sql);
408     $result = array();
409     if (!is_a($res, 'PEAR_Error')) {
410       while ($val = $res->fetchRow()) {
411         $result[] = $val;
412       }
413     }
414     return $result;
415   }
416
417   // The getInactiveClients returns an array of inactive clients for team.
418   static function getInactiveClients($team_id, $all_fields = false)
419   {
420     $result = array();
421     $mdb2 = getConnection();
422
423     if ($all_fields)
424       $sql = "select * from tt_clients where team_id = $team_id and status = 0 order by upper(name)";
425     else
426       $sql = "select id, name from tt_clients where team_id = $team_id and status = 0 order by upper(name)";
427
428     $res = $mdb2->query($sql);
429     $result = array();
430     if (!is_a($res, 'PEAR_Error')) {
431       while ($val = $res->fetchRow()) {
432         $result[] = $val;
433       }
434     }
435     return $result;
436   }
437
438   // The getAllClients obtains all clients in a given team.
439   static function getAllClients($team_id, $all_fields = false) {
440     $mdb2 = getConnection();
441
442     if ($all_fields)
443       $sql = "select * from tt_clients where team_id = $team_id order by status, upper(name)";
444     else
445       $sql = "select id, name from tt_clients where team_id = $team_id order by status, upper(name)";
446
447     $res = $mdb2->query($sql);
448     $result = array();
449     if (!is_a($res, 'PEAR_Error')) {
450       while ($val = $res->fetchRow()) {
451         $result[] = $val;
452       }
453       return $result;
454     }
455     return false;
456   }
457
458   // The getActiveInvoices returns an array of active invoices for team.
459   static function getActiveInvoices($localizeDates = true)
460   {
461     global $user;
462     $addPaidStatus = $user->isPluginEnabled('ps');
463
464     $result = array();
465     $mdb2 = getConnection();
466
467     if ($user->isClient())
468       $client_part = " and i.client_id = $user->client_id";
469
470     $sql = "select i.id, i.name, i.date, i.client_id, i.status, c.name as client_name from tt_invoices i
471       left join tt_clients c on (c.id = i.client_id)
472       where i.status = 1 and i.team_id = $user->team_id $client_part order by i.name";
473     $res = $mdb2->query($sql);
474     $result = array();
475     if (!is_a($res, 'PEAR_Error')) {
476       $dt = new DateAndTime(DB_DATEFORMAT);
477       while ($val = $res->fetchRow()) {
478         if ($localizeDates) {
479           $dt->parseVal($val['date']);
480           $val['date'] = $dt->toString($user->date_format);
481         }
482         if ($addPaidStatus)
483           $val['paid'] = ttInvoiceHelper::isPaid($val['id']);
484         $result[] = $val;
485       }
486     }
487     return $result;
488   }
489
490   // The getAllInvoices returns an array of all invoices for team.
491   static function getAllInvoices()
492   {
493     global $user;
494
495     $result = array();
496     $mdb2 = getConnection();
497
498     $sql = "select * from tt_invoices where team_id = $user->team_id";
499     $res = $mdb2->query($sql);
500     $result = array();
501     if (!is_a($res, 'PEAR_Error')) {
502       $dt = new DateAndTime(DB_DATEFORMAT);
503       while ($val = $res->fetchRow()) {
504         $result[] = $val;
505       }
506     }
507     return $result;
508   }
509
510   // The getRecentInvoices returns an array of recent invoices (max 3) for a client.
511   static function getRecentInvoices($team_id, $client_id)
512   {
513     global $user;
514
515     $result = array();
516     $mdb2 = getConnection();
517
518     $sql = "select i.id, i.name from tt_invoices i
519       left join tt_clients c on (c.id = i.client_id)
520       where i.team_id = $team_id and i.status = 1 and c.id = $client_id
521       order by i.id desc limit 3";
522     $res = $mdb2->query($sql);
523     $result = array();
524     if (!is_a($res, 'PEAR_Error')) {
525       $dt = new DateAndTime(DB_DATEFORMAT);
526       while ($val = $res->fetchRow()) {
527         $result[] = $val;
528       }
529     }
530     return $result;
531   }
532
533   // getUserToProjectBinds - obtains all user to project binds for a team.
534   static function getUserToProjectBinds($team_id) {
535     $mdb2 = getConnection();
536
537     $result = array();
538     $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";
539     $res = $mdb2->query($sql);
540     $result = array();
541     if (!is_a($res, 'PEAR_Error')) {
542       while ($val = $res->fetchRow()) {
543         $result[] = $val;
544       }
545       return $result;
546     }
547     return false;
548   }
549
550   // The getAllCustomFields obtains all custom fields in a given team.
551   static function getAllCustomFields($team_id) {
552     $mdb2 = getConnection();
553
554     $sql = "select * from tt_custom_fields where team_id = $team_id order by status";
555
556     $res = $mdb2->query($sql);
557     $result = array();
558     if (!is_a($res, 'PEAR_Error')) {
559       while ($val = $res->fetchRow()) {
560         $result[] = $val;
561       }
562       return $result;
563     }
564     return false;
565   }
566
567   // The getAllCustomFieldOptions obtains all custom field options in a given team.
568   static function getAllCustomFieldOptions($team_id) {
569     $mdb2 = getConnection();
570
571     $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";
572
573     $res = $mdb2->query($sql);
574     $result = array();
575     if (!is_a($res, 'PEAR_Error')) {
576       while ($val = $res->fetchRow()) {
577         $result[] = $val;
578       }
579       return $result;
580     }
581     return false;
582   }
583
584   // The getCustomFieldLog obtains all custom field log entries for a given team.
585   static function getCustomFieldLog($team_id) {
586     $mdb2 = getConnection();
587
588     $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";
589
590     $res = $mdb2->query($sql);
591     $result = array();
592     if (!is_a($res, 'PEAR_Error')) {
593       while ($val = $res->fetchRow()) {
594         $result[] = $val;
595       }
596       return $result;
597     }
598     return false;
599   }
600
601   // getFavReports - obtains all favorite reports for all users in team.
602   static function getFavReports($team_id) {
603     $mdb2 = getConnection();
604
605     $result = array();
606     $sql = "select * from tt_fav_reports where user_id in (select id from tt_users where team_id = $team_id)";
607     $res = $mdb2->query($sql);
608     $result = array();
609     if (!is_a($res, 'PEAR_Error')) {
610       while ($val = $res->fetchRow()) {
611         $result[] = $val;
612       }
613       return $result;
614     }
615     return false;
616   }
617
618   // getExpenseItems - obtains all expense items for all users in team.
619   static function getExpenseItems($team_id) {
620     $mdb2 = getConnection();
621
622     $result = array();
623     $sql = "select * from tt_expense_items where user_id in (select id from tt_users where team_id = $team_id)";
624     $res = $mdb2->query($sql);
625     $result = array();
626     if (!is_a($res, 'PEAR_Error')) {
627       while ($val = $res->fetchRow()) {
628         $result[] = $val;
629       }
630       return $result;
631     }
632     return false;
633   }
634
635   // getPredefinedExpenses - obtains predefined expenses for team.
636   static function getPredefinedExpenses($team_id) {
637     global $user;
638     $replaceDecimalMark = ('.' != $user->decimal_mark);
639
640     $mdb2 = getConnection();
641
642     $result = array();
643     $sql = "select id, name, cost from tt_predefined_expenses where team_id = $team_id";
644     $res = $mdb2->query($sql);
645     $result = array();
646     if (!is_a($res, 'PEAR_Error')) {
647       while ($val = $res->fetchRow()) {
648         if ($replaceDecimalMark)
649           $val['cost'] = str_replace('.', $user->decimal_mark, $val['cost']);
650         $result[] = $val;
651       }
652       return $result;
653     }
654     return false;
655   }
656
657   // getNotifications - obtains notification descriptions for team.
658   static function getNotifications($team_id) {
659     $mdb2 = getConnection();
660
661     $result = array();
662     $sql = "select c.id, c.cron_spec, c.email, c.report_condition, fr.name from tt_cron c
663       left join tt_fav_reports fr on (fr.id = c.report_id)
664       where c.team_id = $team_id and c.status = 1 and fr.status = 1";
665     $res = $mdb2->query($sql);
666     $result = array();
667     if (!is_a($res, 'PEAR_Error')) {
668       while ($val = $res->fetchRow()) {
669         $result[] = $val;
670       }
671       return $result;
672     }
673     return false;
674   }
675
676   // getMonthlyQuotas - obtains monthly quotas for team.
677   static function getMonthlyQuotas($team_id) {
678     $mdb2 = getConnection();
679
680     $result = array();
681     $sql = "select year, month, minutes from tt_monthly_quotas where team_id = $team_id";
682     $res = $mdb2->query($sql);
683     $result = array();
684     if (!is_a($res, 'PEAR_Error')) {
685       while ($val = $res->fetchRow()) {
686         $result[] = $val;
687       }
688       return $result;
689     }
690     return false;
691   }
692
693   // The markDeleted function marks the team and everything in it as deleted.
694   static function markDeleted($team_id) {
695
696     // Iterate through team users and mark them as deleted.
697     $users = ttTeamHelper::getAllUsers($team_id);
698     foreach ($users as $one_user) {
699       if (!ttUserHelper::markDeleted($one_user['id'])) return false;
700     }
701
702     // Mark tasks deleted.
703     if (!ttTeamHelper::markTasksDeleted($team_id)) return false;
704
705     $mdb2 = getConnection();
706
707     // Mark roles deleted.
708     $sql = "update tt_roles set status = NULL where team_id = $team_id";
709     $affected = $mdb2->exec($sql);
710     if (is_a($affected, 'PEAR_Error')) return false;
711
712     // Mark projects deleted.
713     $sql = "update tt_projects set status = NULL where team_id = $team_id";
714     $affected = $mdb2->exec($sql);
715     if (is_a($affected, 'PEAR_Error')) return false;
716
717     // Mark clients deleted.
718     $sql = "update tt_clients set status = NULL where team_id = $team_id";
719     $affected = $mdb2->exec($sql);
720     if (is_a($affected, 'PEAR_Error')) return false;
721
722     // Mark custom fields deleted.
723     $sql = "update tt_custom_fields set status = NULL where team_id = $team_id";
724     $affected = $mdb2->exec($sql);
725     if (is_a($affected, 'PEAR_Error')) return false;
726
727     // Mark team deleted.
728     $sql = "update tt_teams set status = NULL where id = $team_id";
729     $affected = $mdb2->exec($sql);
730     if (is_a($affected, 'PEAR_Error')) return false;
731
732     return true;
733   }
734
735   // The getTeamDetails function returns team details.
736   static function getTeamDetails($team_id) {
737     $result = array();
738     $mdb2 = getConnection();
739
740     $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
741       from tt_teams t
742       inner join tt_users u on (u.team_id = t.id)
743       inner join tt_roles r on (r.id = u.role_id and r.rank = 512)
744       where t.id = $team_id";
745
746     $res = $mdb2->query($sql);
747     if (!is_a($res, 'PEAR_Error')) {
748       $val = $res->fetchRow();
749       return $val;
750     }
751
752     return false;
753   }
754
755   // The insert function creates a new team.
756   static function insert($fields) {
757
758     $mdb2 = getConnection();
759
760     // Start with team name and currency.
761     $columns = 'name, currency';
762     $values = $mdb2->quote(trim($fields['name'])).', '.$mdb2->quote(trim($fields['currency']));
763
764     if ($fields['decimal_mark']) {
765       $columns .= ', decimal_mark';
766       $values .= ', '.$mdb2->quote($fields['decimal_mark']);
767     }
768
769     $lang = $fields['lang'];
770     if (!$lang) {
771       global $i18n;
772       $lang = $i18n->lang;
773     }
774     $columns .= ', lang';
775     $values .= ', '.$mdb2->quote($lang);
776
777     if ($fields['date_format'] || defined('DATE_FORMAT_DEFAULT')) {
778       $date_format = $fields['date_format'] ? $fields['date_format'] : DATE_FORMAT_DEFAULT;
779       $columns .= ', date_format';
780       $values .= ', '.$mdb2->quote($date_format);
781     }
782
783     if ($fields['time_format'] || defined('TIME_FORMAT_DEFAULT')) {
784       $time_format = $fields['time_format'] ? $fields['time_format'] : TIME_FORMAT_DEFAULT;
785       $columns .= ', time_format';
786       $values .= ', '.$mdb2->quote($time_format);
787     }
788
789     if ($fields['week_start'] || defined('WEEK_START_DEFAULT')) {
790       $week_start = $fields['week_start'] ? $fields['week_start'] : WEEK_START_DEFAULT;
791       $columns .= ', week_start';
792       $values .= ', '.(int)$week_start;
793     }
794
795     if ($fields['tracking_mode']) {
796       $columns .= ', tracking_mode';
797       $values .= ', '.(int)$fields['tracking_mode'];
798     }
799
800     if ($fields['project_required']) {
801       $columns .= ', project_required';
802       $values .= ', '.(int)$fields['project_required'];
803     }
804
805     if ($fields['task_required']) {
806       $columns .= ', task_required';
807       $values .= ', '.(int)$fields['task_required'];
808     }
809
810     if ($fields['record_type']) {
811       $columns .= ', record_type';
812       $values .= ', '.(int)$fields['record_type'];
813     }
814
815     if ($fields['bcc_email']) {
816       $columns .= ', bcc_email';
817       $values .= ', '.$mdb2->quote($fields['bcc_email']);
818     }
819
820     if ($fields['plugins']) {
821       $columns .= ', plugins';
822       $values .= ', '.$mdb2->quote($fields['plugins']);
823     }
824
825     if ($fields['lock_spec']) {
826       $columns .= ', lock_spec';
827       $values .= ', '.$mdb2->quote($fields['lock_spec']);
828     }
829
830     if ($fields['workday_minutes']) {
831       $columns .= ', workday_minutes';
832       $values .= ', '.(int)$fields['workday_minutes'];
833     }
834
835     if ($fields['config']) {
836       $columns .= ', config';
837       $values .= ', '.$mdb2->quote($fields['config']);
838     }
839
840     $sql = "insert into tt_teams ($columns) values($values)";
841     $affected = $mdb2->exec($sql);
842
843     if (!is_a($affected, 'PEAR_Error')) {
844       $team_id = $mdb2->lastInsertID('tt_teams', 'id');
845       return $team_id;
846     }
847
848     return false;
849   }
850
851   // The update function updates team information.
852   static function update($team_id, $fields)
853   {
854     global $user;
855     $mdb2 = getConnection();
856     $name_part = 'name = '.$mdb2->quote($fields['name']);
857     $currency_part = '';
858     $lang_part = '';
859     $decimal_mark_part = '';
860     $date_format_part = '';
861     $time_format_part = '';
862     $week_start_part = '';
863     $tracking_mode_part = '';
864     $task_required_part = ' , task_required = '.(int) $fields['task_required'];
865     $record_type_part = '';
866     $bcc_email_part = '';
867     $plugins_part = '';
868     $config_part = '';
869     $lock_spec_part = '';
870     $workday_minutes_part = '';
871
872     if (isset($fields['currency'])) $currency_part = ', currency = '.$mdb2->quote($fields['currency']);
873     if (isset($fields['lang'])) $lang_part = ', lang = '.$mdb2->quote($fields['lang']);
874     if (isset($fields['decimal_mark'])) $decimal_mark_part = ', decimal_mark = '.$mdb2->quote($fields['decimal_mark']);
875     if (isset($fields['date_format'])) $date_format_part = ', date_format = '.$mdb2->quote($fields['date_format']);
876     if (isset($fields['time_format'])) $time_format_part = ', time_format = '.$mdb2->quote($fields['time_format']);
877     if (isset($fields['week_start'])) $week_start_part = ', week_start = '.(int) $fields['week_start'];
878     if (isset($fields['tracking_mode'])) $tracking_mode_part = ', tracking_mode = '.(int) $fields['tracking_mode'];
879     if (isset($fields['record_type'])) $record_type_part = ', record_type = '.(int) $fields['record_type'];
880     if (isset($fields['bcc_email'])) $bcc_email_part = ', bcc_email = '.$mdb2->quote($fields['bcc_email']);
881     if (isset($fields['plugins'])) $plugins_part = ', plugins = '.$mdb2->quote($fields['plugins']);
882     if (isset($fields['config'])) $config_part = ', config = '.$mdb2->quote($fields['config']);
883     if (isset($fields['lock_spec'])) $lock_spec_part = ', lock_spec = '.$mdb2->quote($fields['lock_spec']);
884     if (isset($fields['workday_minutes'])) $workday_minutes_part = ', workday_minutes = '.$mdb2->quote($fields['workday_minutes']);
885     $modified_part = ', modified = now(), modified_ip = '.$mdb2->quote($_SERVER['REMOTE_ADDR']).', modified_by = '.$mdb2->quote($user->id);
886
887     $sql = "update tt_teams set $name_part $currency_part $lang_part $decimal_mark_part
888       $date_format_part $time_format_part $week_start_part $tracking_mode_part $task_required_part $record_type_part
889       $bcc_email_part $plugins_part $config_part $lock_spec_part $workday_minutes_part $modified_part where id = $team_id";
890     $affected = $mdb2->exec($sql);
891     if (is_a($affected, 'PEAR_Error')) return false;
892
893     return true;
894   }
895
896   // The getInactiveTeams is a maintenance function that returns an array of inactive team ids (max 100).
897   static function getInactiveTeams() {
898     $inactive_teams = array();
899     $mdb2 = getConnection();
900
901     // Get all team ids for teams created or modified more than 8 months ago.
902     // $ts = date('Y-m-d', strtotime('-1 year'));
903     $ts = $mdb2->quote(date('Y-m-d', strtotime('-8 month')));
904     $sql =  "select id from tt_teams where created < $ts and (modified is null or modified < $ts) order by id";
905     $res = $mdb2->query($sql);
906
907     $count = 0;
908     if (!is_a($res, 'PEAR_Error')) {
909       while ($val = $res->fetchRow()) {
910         $team_id = $val['id'];
911         if (ttTeamHelper::isTeamActive($team_id) == false) {
912           $count++;
913           $inactive_teams[] = $team_id;
914           // Limit the array size for perfomance by allowing this operation on small chunks only.
915           if ($count >= 100) break;
916         }
917       }
918       return $inactive_teams;
919     }
920     return false;
921   }
922
923   // The isTeamActive determines if a team is using Time Tracker or abandoned it.
924   static function isTeamActive($team_id) {
925     $users = array();
926
927     $mdb2 = getConnection();
928     $sql = "select id from tt_users where team_id = $team_id";
929     $res = $mdb2->query($sql);
930     if (is_a($res, 'PEAR_Error')) die($res->getMessage());
931     while ($val = $res->fetchRow()) {
932       $users[] = $val['id'];
933     }
934     $user_list = implode(',', $users); // This is a comma-separated list of user ids.
935     if (!$user_list)
936       return false; // No users in team.
937
938     $count = 0;
939     $ts = date('Y-m-d', strtotime('-2 years'));
940     $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and created > '$ts'";
941     $res = $mdb2->query($sql);
942     if (!is_a($res, 'PEAR_Error')) {
943       if ($val = $res->fetchRow()) {
944         $count = $val['cnt'];
945       }
946     }
947
948     if ($count == 0)
949       return false;  // No time entries for the last 2 years.
950
951     if ($count <= 5) {
952       // We will consider a team inactive if it has 5 or less time entries made more than 1 year ago.
953       $count_last_year = 0;
954       $ts = date('Y-m-d', strtotime('-1 year'));
955       $sql = "select count(*) as cnt from tt_log where user_id in ($user_list) and created > '$ts'";
956       $res = $mdb2->query($sql);
957       if (!is_a($res, 'PEAR_Error')) {
958         if ($val = $res->fetchRow()) {
959           $count_last_year = $val['cnt'];
960         }
961         if ($count_last_year == 0)
962           return false;  // No time entries for the last year and only a few entries before that.
963       }
964     }
965     return true;
966   }
967
968   // The delete function permanently deletes all data for a team.
969   static function delete($team_id) {
970     $mdb2 = getConnection();
971
972     // Delete users.
973     $sql = "select id from tt_users where team_id = $team_id";
974     $res = $mdb2->query($sql);
975     if (is_a($res, 'PEAR_Error')) return false;
976     while ($val = $res->fetchRow()) {
977       $user_id = $val['id'];
978       if (!ttUserHelper::delete($user_id)) return false;
979     }
980
981     // Delete tasks.
982     if (!ttTeamHelper::deleteTasks($team_id)) return false;
983
984     // Delete client to project binds.
985     $sql = "delete from tt_client_project_binds where client_id in (select id from tt_clients where team_id = $team_id)";
986     $affected = $mdb2->exec($sql);
987     if (is_a($affected, 'PEAR_Error')) return false;
988
989     // Delete projects.
990     $sql = "delete from tt_projects where team_id = $team_id";
991     $affected = $mdb2->exec($sql);
992     if (is_a($affected, 'PEAR_Error')) return false;
993
994     // Delete clients.
995     $sql = "delete from tt_clients where team_id = $team_id";
996     $affected = $mdb2->exec($sql);
997     if (is_a($affected, 'PEAR_Error')) return false;
998
999     // Delete invoices.
1000     $sql = "delete from tt_invoices where team_id = $team_id";
1001     $affected = $mdb2->exec($sql);
1002     if (is_a($affected, 'PEAR_Error')) return false;
1003
1004     // Delete custom fields.
1005     if (!ttTeamHelper::deleteCustomFields($team_id)) return false;
1006
1007     // Delete roles.
1008     $sql = "delete from tt_roles where team_id = $team_id";
1009     $affected = $mdb2->exec($sql);
1010     if (is_a($affected, 'PEAR_Error')) return false;
1011
1012     // Delete team.
1013     $sql = "delete from tt_teams where id = $team_id";
1014     $affected = $mdb2->exec($sql);
1015     if (is_a($affected, 'PEAR_Error')) return false;
1016
1017     return true;
1018   }
1019
1020   // The markTasksDeleted deletes task binds and marks the tasks as deleted for a team.
1021   static function markTasksDeleted($team_id) {
1022     $mdb2 = getConnection();
1023     $sql = "select id from tt_tasks where team_id = $team_id";
1024     $res = $mdb2->query($sql);
1025     if (is_a($res, 'PEAR_Error')) return false;
1026
1027     while ($val = $res->fetchRow()) {
1028
1029       // Delete task binds.
1030       $task_id = $val['id'];
1031       $sql = "delete from tt_project_task_binds where task_id = $task_id";
1032       $affected = $mdb2->exec($sql);
1033       if (is_a($affected, 'PEAR_Error')) return false;
1034
1035       // Mark task as deleted.
1036       $sql = "update tt_tasks set status = NULL where id = $task_id";
1037       $affected = $mdb2->exec($sql);
1038       if (is_a($affected, 'PEAR_Error')) return false;
1039     }
1040
1041     return true;
1042   }
1043
1044   // The deleteTasks deletes all tasks and task binds for an inactive team.
1045   static function deleteTasks($team_id) {
1046     $mdb2 = getConnection();
1047     $sql = "select id from tt_tasks where team_id = $team_id";
1048     $res = $mdb2->query($sql);
1049     if (is_a($res, 'PEAR_Error')) return false;
1050
1051     while ($val = $res->fetchRow()) {
1052
1053       // Delete task binds.
1054       $task_id = $val['id'];
1055       $sql = "delete from tt_project_task_binds where task_id = $task_id";
1056       $affected = $mdb2->exec($sql);
1057       if (is_a($affected, 'PEAR_Error')) return false;
1058
1059       // Delete task.
1060       $sql = "delete from tt_tasks where id = $task_id";
1061       $affected = $mdb2->exec($sql);
1062       if (is_a($affected, 'PEAR_Error')) return false;
1063     }
1064
1065     return true;
1066   }
1067
1068   // The deleteCustomFields cleans up tt_custom_field_log, tt_custom_field_options and tt_custom_fields tables for an inactive team.
1069   static function deleteCustomFields($team_id) {
1070     $mdb2 = getConnection();
1071     $sql = "select id from tt_custom_fields where team_id = $team_id";
1072     $res = $mdb2->query($sql);
1073     if (is_a($res, 'PEAR_Error')) return false;
1074
1075     while ($val = $res->fetchRow()) {
1076       $field_id = $val['id'];
1077
1078       // Clean up tt_custom_field_log.
1079       $sql = "delete from tt_custom_field_log where field_id = $field_id";
1080       $affected = $mdb2->exec($sql);
1081       if (is_a($affected, 'PEAR_Error')) return false;
1082
1083       // Clean up tt_custom_field_options.
1084       $sql = "delete from tt_custom_field_options where field_id = $field_id";
1085       $affected = $mdb2->exec($sql);
1086       if (is_a($affected, 'PEAR_Error')) return false;
1087
1088       // Delete custom field.
1089       $sql = "delete from tt_custom_fields where id = $field_id";
1090       $affected = $mdb2->exec($sql);
1091       if (is_a($affected, 'PEAR_Error')) return false;
1092     }
1093
1094     return true;
1095   }
1096
1097   // enablePlugin either enables or disables a specific plugin for team.
1098   static function enablePlugin($plugin, $enable = true)
1099   {
1100     global $user;
1101     if (!$user->can('manage_features'))
1102       return false;
1103
1104     $plugin_array = explode(',', $user->plugins);
1105     if ($enable && !in_array($plugin, $plugin_array))
1106       $plugin_array[] = $plugin; // Add plugin to array.
1107
1108     if (!$enable && in_array($plugin, $plugin_array)) {
1109       $key = array_search($plugin, $plugin_array);
1110       if ($key !== false)
1111         unset($plugin_array[$key]); // Remove plugin from array.
1112     }
1113
1114     $plugins = implode(',', $plugin_array);
1115     if ($plugins != $user->plugins) {
1116       if (!ttTeamHelper::update($user->team_id, array('name' => $user->team,'plugins' => $plugins)))
1117         return false;
1118       $user->plugins = $plugins;
1119     }
1120
1121     return true;
1122   }
1123 }