forked from anuko/timetracker
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathttOrgHelper.class.php
More file actions
213 lines (186 loc) · 7.51 KB
/
ttOrgHelper.class.php
File metadata and controls
213 lines (186 loc) · 7.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<?php
// +----------------------------------------------------------------------+
// | Anuko Time Tracker
// +----------------------------------------------------------------------+
// | Copyright (c) Anuko International Ltd. (https://www.anuko.com)
// +----------------------------------------------------------------------+
// | LIBERAL FREEWARE LICENSE: This source code document may be used
// | by anyone for any purpose, and freely redistributed alone or in
// | combination with other software, provided that the license is obeyed.
// |
// | There are only two ways to violate the license:
// |
// | 1. To redistribute this code in source form, with the copyright
// | notice or license removed or altered. (Distributing in compiled
// | forms without embedded copyright notices is permitted).
// |
// | 2. To redistribute modified versions of this code in *any* form
// | that bears insufficient indications that the modifications are
// | not the work of the original author(s).
// |
// | This license applies to this document only, not any other software
// | that it may be combined with.
// |
// +----------------------------------------------------------------------+
// | Contributors:
// | https://www.anuko.com/time-tracker/credits.htm
// +----------------------------------------------------------------------+
// Class ttOrgHelper contains helper functions that operate with organizations.
// Organizations are collections of nested groups of users.
class ttOrgHelper {
// The getOrgs function returns an array of all active organizations on the server.
static function getOrgs() {
$result = array();
$mdb2 = getConnection();
$sql = "select id, name, created, lang from tt_groups".
" where status = 1 and org_id = id and parent_id is NULL order by id desc";
$res = $mdb2->query($sql);
$result = array();
if (!is_a($res, 'PEAR_Error')) {
while ($val = $res->fetchRow()) {
$val['date'] = substr($val['created'], 0, 10); // Strip the time.
$result[] = $val;
}
return $result;
}
return false;
}
// The getName function returns organization name (which is a name of its top group).
static function getName($org_id) {
$mdb2 = getConnection();
$sql = "select name from tt_groups where id = $org_id and (status = 1 or status = 0) and parent_id is NULL";
$res = $mdb2->query($sql);
if (!is_a($res, 'PEAR_Error')) {
$val = $res->fetchRow();
return $val['name'];
}
return false;
}
// The getInactiveOrgs is a maintenance function that returns an array of inactive organization ids (max 50 for now).
static function getInactiveOrgs() {
$inactive_orgs = array();
$mdb2 = getConnection();
// Construct $org_sizes_part (if we have to).
$sql = "show tables like 'org_sizes'";
$res = $mdb2->query($sql);
$org_sizes_part = "";
if (!is_a($res, 'PEAR_Error') && $res->fetchRow()) {
// org_sizes table exist.
$sql = "select org_id from org_sizes order by org_id";
$res = $mdb2->query($sql);
if (!is_a($res, 'PEAR_Error')) {
while ($val = $res->fetchRow()) {
$orgs_to_ignore[] = $val['org_id'];
}
$comma_separated = implode(',', $orgs_to_ignore);
if ($comma_separated) {
$org_sizes_part = " and org_id not in ($comma_separated)";
}
}
}
// Determine inactive organizations by querying the database for max access timestamp for its users.
$cutoff_timestamp = $mdb2->quote(date('Y-m-d', strtotime('-1 year')));
$sql = "select org_id from".
" (select max(accessed) as last_access, org_id from tt_users where org_id > 0".$org_sizes_part." group by org_id order by last_access, org_id) as t".
" where last_access is null or last_access < $cutoff_timestamp limit 50"; // Max 50 orgs at a time for now...
$res = $mdb2->query($sql);
if (!is_a($res, 'PEAR_Error')) {
while ($val = $res->fetchRow()) {
$inactive_orgs[] = $val['org_id'];
}
return $inactive_orgs;
}
return false;
}
// deleteOrg deletes data for the entire organization from database permanently.
static function deleteOrg($org_id) {
// Delete all org files.
ttOrgHelper::deleteOrgFiles($org_id);
// Go one table at a time and remove all records with matching org_id.
// The order is backwards to import (see ttOrgImportHelper). Remove groups last.
// This leaves us with something partially working if an error occurs.
$mdb2 = getConnection();
$tables = array(
'tt_config',
'tt_cron',
'tt_fav_reports',
'tt_project_template_binds',
'tt_templates',
'tt_monthly_quotas',
'tt_predefined_expenses',
'tt_expense_items',
'tt_custom_field_log',
'tt_custom_field_options',
'tt_custom_fields',
'tt_log',
'tt_invoices',
'tt_timesheets',
'tt_user_project_binds',
'tt_users',
'tt_client_project_binds',
'tt_clients',
'tt_project_task_binds',
'tt_projects',
'tt_tasks',
'tt_roles',
'tt_groups'
);
foreach($tables as $table) {
$sql = "delete from $table where org_id = $org_id";
$affected = $mdb2->exec($sql);
if (is_a($affected, 'PEAR_Error')) return false;
}
return true; }
// deleteOrgFiles deletes files attached to all entities in the entire organization.
static function deleteOrgFiles($org_id) {
// Delete all org files from the database.
$mdb2 = getConnection();
$sql = "delete from tt_files where org_id = $org_id";
$affected = $mdb2->exec($sql);
if (is_a($affected, 'PEAR_Error'))
return false;
if ($affected == 0) return true; // Do not call file storage utility.
// Try to make a call to file storage server.
$storage_uri = defined('FILE_STORAGE_URI') ? FILE_STORAGE_URI : "https://www.anuko.com/files/";
$deleteorgfiles_uri = $storage_uri.'deleteorgfiles';
// Obtain site id.
$sql = "select param_value as site_id from tt_site_config where param_name = 'locker_id'";
$res = $mdb2->query($sql);
$val = $res->fetchRow();
$site_id = $val['site_id'];
if (!$site_id) return true; // Nothing to do.
// Obtain site key.
$sql = "select param_value as site_key from tt_site_config where param_name = 'locker_key'";
$res = $mdb2->query($sql);
$val = $res->fetchRow();
$site_key = $val['site_key'];
if (!$site_key) return true; // Can't continue without site key.
// Obtain org key.
$sql = "select group_key as org_key from tt_groups where id = $org_id";
$res = $mdb2->query($sql);
$val = $res->fetchRow();
$org_key = $val['org_key'];
if (!$org_key) return true; // Can't continue without org key.
$curl_fields = array('site_id' => $site_id,
'site_key' => $site_key,
'org_id' => $org_id,
'org_key' => $org_key);
// url-ify the data for the POST.
foreach($curl_fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
$fields_string = rtrim($fields_string, '&');
// Open connection.
$ch = curl_init();
// Set the url, number of POST vars, POST data.
curl_setopt($ch, CURLOPT_URL, $deleteorgfiles_uri);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Execute a post request.
$result = curl_exec($ch);
// Close connection.
curl_close($ch);
// Many things can go wrong with a remote call to file storage facility.
// By design, we ignore such errors.
return true;
}
}