1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
//------------------------------------------------------------------------------ |
4
|
|
|
// |
5
|
|
|
// eTraxis - Records tracking web-based system |
6
|
|
|
// Copyright (C) 2005-2012 Artem Rodygin |
7
|
|
|
// |
8
|
|
|
// This program is free software: you can redistribute it and/or modify |
9
|
|
|
// it under the terms of the GNU General Public License as published by |
10
|
|
|
// the Free Software Foundation, either version 3 of the License, or |
11
|
|
|
// (at your option) any later version. |
12
|
|
|
// |
13
|
|
|
// This program is distributed in the hope that it will be useful, |
14
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
15
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16
|
|
|
// GNU General Public License for more details. |
17
|
|
|
// |
18
|
|
|
// You should have received a copy of the GNU General Public License |
19
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
20
|
|
|
// |
21
|
|
|
//------------------------------------------------------------------------------ |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Records |
25
|
|
|
* |
26
|
|
|
* This module provides API to work with records. |
27
|
|
|
* See also {@link https://github.com/etraxis/etraxis-obsolete/wiki/tbl_records tbl_records} database table. |
28
|
|
|
* |
29
|
|
|
* @package DBO |
30
|
|
|
* @subpackage Records |
31
|
|
|
*/ |
32
|
|
|
|
33
|
|
|
/**#@+ |
34
|
|
|
* Dependency. |
35
|
|
|
*/ |
36
|
|
|
require_once('../engine/engine.php'); |
37
|
|
|
require_once('../dbo/accounts.php'); |
38
|
|
|
require_once('../dbo/filters.php'); |
39
|
|
|
require_once('../dbo/fields.php'); |
40
|
|
|
require_once('../dbo/values.php'); |
41
|
|
|
require_once('../dbo/events.php'); |
42
|
|
|
/**#@-*/ |
43
|
|
|
|
44
|
|
|
//------------------------------------------------------------------------------ |
45
|
|
|
// Definitions. |
46
|
|
|
//------------------------------------------------------------------------------ |
47
|
|
|
|
48
|
|
|
/**#@+ |
49
|
|
|
* Data restrictions. |
50
|
|
|
*/ |
51
|
|
|
define('MAX_RECORD_SUBJECT', 250); |
52
|
|
|
define('MAX_COMMENT_BODY', 4000); |
53
|
|
|
define('MAX_ATTACHMENT_NAME', 100); |
54
|
|
|
define('MAX_SEARCH_TEXT', 100); |
55
|
|
|
define('MAX_SEARCH_WORDS', 5); |
56
|
|
|
/**#@-*/ |
57
|
|
|
|
58
|
|
|
/**#@+ |
59
|
|
|
* Record operations. |
60
|
|
|
*/ |
61
|
|
|
define('OPERATION_CREATE_RECORD', 1); |
62
|
|
|
define('OPERATION_MODIFY_RECORD', 2); |
63
|
|
|
define('OPERATION_CHANGE_STATE', 3); |
64
|
|
|
/**#@-*/ |
65
|
|
|
|
66
|
|
|
/**#@+ |
67
|
|
|
* Tabs on record view page. |
68
|
|
|
*/ |
69
|
|
|
define('RECORD_TAB_MAIN', 1); |
70
|
|
|
define('RECORD_TAB_HISTORY', 2); |
71
|
|
|
define('RECORD_TAB_CHANGES', 3); |
72
|
|
|
define('RECORD_TAB_FIELDS', 4); |
73
|
|
|
define('RECORD_TAB_COMMENTS', 5); |
74
|
|
|
define('RECORD_TAB_ATTACHMENTS', 6); |
75
|
|
|
define('RECORD_TAB_PARENTS', 7); |
76
|
|
|
define('RECORD_TAB_SUBRECORDS', 8); |
77
|
|
|
/**#@-*/ |
78
|
|
|
|
79
|
|
|
//------------------------------------------------------------------------------ |
80
|
|
|
// Functions. |
81
|
|
|
//------------------------------------------------------------------------------ |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Formats specified record ID, adding template prefix if specified and leading zeroes if required. |
85
|
|
|
* |
86
|
|
|
* @param int $id Record ID. |
87
|
|
|
* @param string $prefix Template prefix. |
88
|
|
|
* @return string Formatted record ID. |
89
|
|
|
*/ |
90
|
|
|
function record_id ($id, $prefix = NULL) |
91
|
|
|
{ |
92
|
|
|
debug_write_log(DEBUG_TRACE, '[record_id]'); |
93
|
|
|
debug_write_log(DEBUG_DUMP, '[record_id] $id = ' . $id); |
94
|
|
|
debug_write_log(DEBUG_DUMP, '[record_id] $prefix = ' . $prefix); |
95
|
|
|
|
96
|
|
|
return ustr2html((is_null($prefix) ? NULL : $prefix . '-') . str_pad($id, 3, '0', STR_PAD_LEFT)); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* Finds in database and returns the information about specified record. |
101
|
|
|
* |
102
|
|
|
* @param int $id Record ID. |
103
|
|
|
* @return array Array with data if record is found in database, FALSE otherwise. |
104
|
|
|
*/ |
105
|
|
|
function record_find ($id) |
106
|
|
|
{ |
107
|
|
|
debug_write_log(DEBUG_TRACE, '[record_find]'); |
108
|
|
|
debug_write_log(DEBUG_DUMP, '[record_find] $id = ' . $id); |
109
|
|
|
|
110
|
|
|
$rs = dal_query('records/fndid.sql', $id, time()); |
111
|
|
|
|
112
|
|
|
return ($rs->rows == 0 ? FALSE : $rs->fetch()); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Returns {@link CRecordset DAL recordset} which contains all records, allowed to be displayed |
117
|
|
|
* in accordance to current set of filters, search mode, user permissions, etc. |
118
|
|
|
* Recordset is sorted in accordance with current sort mode. |
119
|
|
|
* |
120
|
|
|
* @param array $columns List of columns (see {@link column_list}). |
121
|
|
|
* @param int &$sort Sort mode (used as output only). The function retrieves current sort mode from |
122
|
|
|
* client cookie ({@link COOKIE_RECORDS_SORT}) and updates it, if it's out of valid range. |
123
|
|
|
* @param int &$page Number of current page tab (used as output only). The function retrieves current |
124
|
|
|
* page from client cookie ({@link COOKIE_RECORDS_PAGE}) and updates it, if it's out of valid range. |
125
|
|
|
* @param bool $search_mode Whether the search mode is on. |
126
|
|
|
* @param string $search_text Text to be searched (ignored when search mode is off). |
127
|
|
|
* @return CRecordset Recordset with list of records. |
128
|
|
|
*/ |
129
|
|
|
function records_list ($columns, &$sort, &$page, $search_mode = FALSE, $search_text = NULL) |
130
|
|
|
{ |
131
|
|
|
debug_write_log(DEBUG_TRACE, '[records_list]'); |
132
|
|
|
|
133
|
|
|
$sort = try_request('sort', try_cookie(COOKIE_RECORDS_SORT . $_SESSION[VAR_VIEW])); |
134
|
|
|
$sort = ustr2int($sort, -count($columns), count($columns)); |
135
|
|
|
|
136
|
|
|
$page = try_request('page', try_cookie(COOKIE_RECORDS_PAGE . $_SESSION[VAR_VIEW])); |
137
|
|
|
$page = ustr2int($page, 1, MAXINT); |
138
|
|
|
|
139
|
|
|
$date = getdate(); |
140
|
|
|
$time = mktime(23, 59, 59, $date['mon'], $date['mday'], $date['year']); |
141
|
|
|
|
142
|
|
|
$clause_select = array('r.record_id', |
143
|
|
|
'r.subject', |
144
|
|
|
'r.responsible_id', |
145
|
|
|
'r.creator_id', |
146
|
|
|
'r.creation_time', |
147
|
|
|
'r.change_time', |
148
|
|
|
'r.closure_time', |
149
|
|
|
'r.postpone_time', |
150
|
|
|
'p.project_name', |
151
|
|
|
't.template_name', |
152
|
|
|
't.template_prefix', |
153
|
|
|
't.critical_age', |
154
|
|
|
's.state_name', |
155
|
|
|
's.state_abbr'); |
156
|
|
|
|
157
|
|
|
$clause_from = array('tbl_projects p', |
158
|
|
|
'tbl_states s'); |
159
|
|
|
|
160
|
|
|
$clause_join = array('tbl_records r'); |
161
|
|
|
|
162
|
|
|
$clause_where = array('p.project_id = t.project_id', |
163
|
|
|
't.template_id = s.template_id', |
164
|
|
|
's.state_id = r.state_id'); |
165
|
|
|
|
166
|
|
|
save_cookie(COOKIE_RECORDS_SORT . $_SESSION[VAR_VIEW], $sort); |
167
|
|
|
save_cookie(COOKIE_RECORDS_PAGE . $_SESSION[VAR_VIEW], $page); |
168
|
|
|
|
169
|
|
|
// Add default access conditions for guests and registered users. |
170
|
|
|
|
171
|
|
|
if (get_user_level() == USER_LEVEL_GUEST) |
172
|
|
|
{ |
173
|
|
|
array_push($clause_select, '0 as read_time'); |
174
|
|
|
array_push($clause_from, 'tbl_templates t'); |
175
|
|
|
array_push($clause_where, 't.guest_access = 1'); |
176
|
|
|
array_push($clause_where, 'r.closure_time is null'); |
177
|
|
|
} |
178
|
|
|
else |
179
|
|
|
{ |
180
|
|
|
$perms = 'select gp.template_id, count(gp.group_id) as gnum ' |
181
|
|
|
. 'from tbl_membership ms, tbl_group_perms gp ' |
182
|
|
|
. 'where ms.account_id = %1 and ms.group_id = gp.group_id and ' |
183
|
|
|
. (DATABASE_DRIVER == DRIVER_ORACLE9 ? 'mod(floor(gp.perms / %2), 2) = 1 ' : '(gp.perms & %2) <> 0 ') |
184
|
|
|
. 'group by template_id'; |
185
|
|
|
|
186
|
|
|
$perms = ustrprocess($perms, $_SESSION[VAR_USERID], PERMIT_VIEW_RECORD); |
187
|
|
|
|
188
|
|
|
array_push($clause_from, "tbl_templates t left outer join ({$perms}) perms on t.template_id = perms.template_id"); |
189
|
|
|
array_push($clause_where, ustrprocess('(perms.gnum is not null' . |
190
|
|
|
' or r.creator_id = %1' . |
191
|
|
|
' or r.responsible_id = %1' . |
192
|
|
|
' or ' . (DATABASE_DRIVER == DRIVER_ORACLE9 ? 'mod(floor(t.registered_perm / %2), 2) = 1' : '(t.registered_perm & %2) <> 0') . |
193
|
|
|
' or t.guest_access = 1)', |
194
|
|
|
$_SESSION[VAR_USERID], PERMIT_VIEW_RECORD)); |
195
|
|
|
|
196
|
|
|
array_push($clause_select, 'rd.read_time'); |
197
|
|
|
array_push($clause_join, 'left outer join tbl_reads rd on rd.record_id = r.record_id and rd.account_id = ' . $_SESSION[VAR_USERID]); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
// Add search conditions if search is activated. |
201
|
|
|
|
202
|
|
|
if ($search_mode) |
203
|
|
|
{ |
204
|
|
|
debug_write_log(DEBUG_NOTICE, '[records_list] Search mode is turned on.'); |
205
|
|
|
debug_write_log(DEBUG_DUMP, '[records_list] $search_text = ' . $search_text); |
206
|
|
|
|
207
|
|
|
$search = array(); |
208
|
|
|
|
209
|
|
|
if (is_intvalue($search_text)) |
210
|
|
|
{ |
211
|
|
|
array_push($search, |
212
|
|
|
'select e.record_id ' . |
213
|
|
|
'from tbl_events e, tbl_field_values fv ' . |
214
|
|
|
'where e.event_id = fv.event_id and fv.field_type = ' . FIELD_TYPE_NUMBER . ' and fv.is_latest = 1 and fv.value_id = ' . $search_text); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
$search_text = "'%" . ustr2sql(ustrtolower($search_text)) . "%'"; |
218
|
|
|
|
219
|
|
|
$search_in_subject = (in_array(DATABASE_DRIVER, array(DRIVER_ORACLE9, DRIVER_PGSQL80)) ? 'lower' : NULL) . '(r.subject) like ' . $search_text; |
220
|
|
|
$search_in_svalues = (in_array(DATABASE_DRIVER, array(DRIVER_ORACLE9, DRIVER_PGSQL80)) ? 'lower' : NULL) . '(sv.string_value) like ' . $search_text; |
221
|
|
|
$search_in_tvalues = (in_array(DATABASE_DRIVER, array(DRIVER_ORACLE9, DRIVER_PGSQL80)) ? 'lower' : NULL) . '(tv.text_value) like ' . $search_text; |
222
|
|
|
$search_in_comments = (in_array(DATABASE_DRIVER, array(DRIVER_ORACLE9, DRIVER_PGSQL80)) ? 'lower' : NULL) . '(c.comment_body) like ' . $search_text; |
223
|
|
|
|
224
|
|
|
array_push($search, |
225
|
|
|
'select r.record_id ' . |
226
|
|
|
'from tbl_records r ' . |
227
|
|
|
'where ' . $search_in_subject); |
228
|
|
|
|
229
|
|
|
array_push($search, |
230
|
|
|
'select e.record_id ' . |
231
|
|
|
'from tbl_events e, tbl_field_values fv, tbl_string_values sv ' . |
232
|
|
|
'where e.event_id = fv.event_id and fv.field_type = ' . FIELD_TYPE_STRING . ' and fv.value_id = sv.value_id and fv.is_latest = 1 and ' . |
233
|
|
|
$search_in_svalues); |
234
|
|
|
|
235
|
|
|
array_push($search, |
236
|
|
|
'select e.record_id ' . |
237
|
|
|
'from tbl_events e, tbl_field_values fv, tbl_text_values tv ' . |
238
|
|
|
'where e.event_id = fv.event_id and fv.field_type = ' . FIELD_TYPE_MULTILINED . ' and fv.value_id = tv.value_id and fv.is_latest = 1 and ' . |
239
|
|
|
$search_in_tvalues); |
240
|
|
|
|
241
|
|
|
array_push($search, |
242
|
|
|
'select e.record_id ' . |
243
|
|
|
'from tbl_events e, tbl_comments c ' . |
244
|
|
|
'where e.event_id = c.event_id and ' . |
245
|
|
|
$search_in_comments); |
246
|
|
|
|
247
|
|
|
$sql = 'select record_id from (' . implode(' union ', $search) . ') data'; |
248
|
|
|
|
249
|
|
|
$ids = array(); |
250
|
|
|
$rsx = new CRecordset($sql); |
251
|
|
|
|
252
|
|
|
while (($row = $rsx->fetch())) |
253
|
|
|
{ |
254
|
|
|
array_push($ids, $row['record_id']); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
$search_ids = (count($ids) == 0) |
258
|
|
|
? 'NULL' |
259
|
|
|
: implode(', ', $ids); |
260
|
|
|
|
261
|
|
|
debug_write_log(DEBUG_NOTICE, '[records_list] $search_ids = [' . $search_ids . ']' ); |
262
|
|
|
|
263
|
|
|
array_push($clause_where, 'r.record_id in (' . $search_ids . ')'); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
// Add filters, if it's not a search or if it's a filtered search. |
267
|
|
|
|
268
|
|
|
if (!$search_mode || $_SESSION[VAR_USE_FILTERS]) |
269
|
|
|
{ |
270
|
|
|
debug_write_log(DEBUG_NOTICE, '[records_list] Filters are in use.'); |
271
|
|
|
|
272
|
|
|
$filters = array(); |
273
|
|
|
|
274
|
|
|
$fsort = $fpage = NULL; |
275
|
|
|
$rs = filters_list($_SESSION[VAR_USERID], TRUE, $fsort, $fpage); |
276
|
|
|
|
277
|
|
|
while (($filter = $rs->fetch())) |
278
|
|
|
{ |
279
|
|
|
if ($filter['filter_flags'] == 0 && |
280
|
|
|
$filter['filter_type'] == FILTER_TYPE_ALL_PROJECTS) |
281
|
|
|
{ |
282
|
|
|
continue; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
$clause_filter = array(); |
286
|
|
|
|
287
|
|
|
switch ($filter['filter_type']) |
288
|
|
|
{ |
289
|
|
|
case FILTER_TYPE_ALL_PROJECTS: |
290
|
|
|
break; |
291
|
|
|
|
292
|
|
|
case FILTER_TYPE_ALL_TEMPLATES: |
293
|
|
|
array_push($clause_select, 'p.project_id'); |
294
|
|
|
array_push($clause_filter, 'p.project_id = ' . $filter['filter_param']); |
295
|
|
|
break; |
296
|
|
|
|
297
|
|
|
case FILTER_TYPE_ALL_STATES: |
298
|
|
|
array_push($clause_select, 't.template_id'); |
299
|
|
|
array_push($clause_filter, 't.template_id = ' . $filter['filter_param']); |
300
|
|
|
break; |
301
|
|
|
|
302
|
|
|
case FILTER_TYPE_SEL_STATES: |
303
|
|
|
$states = filter_states_get($filter['filter_id'], $filter['filter_param']); |
304
|
|
|
array_push($clause_select, 's.state_id'); |
305
|
|
|
array_push($clause_filter, 's.state_id in (' . implode(',', array_unique($states)) . ')'); |
306
|
|
|
break; |
307
|
|
|
|
308
|
|
|
default: |
309
|
|
|
debug_write_log(DEBUG_WARNING, '[records_list] Unknown filter type = ' . $filter['filter_type']); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
View Code Duplication |
if ($filter['filter_flags'] & FILTER_FLAG_CREATED_BY) |
|
|
|
|
313
|
|
|
{ |
314
|
|
|
array_push($clause_select, 'r.creator_id'); |
315
|
|
|
array_push($clause_filter, |
316
|
|
|
'r.creator_id in ' . |
317
|
|
|
'(select account_id ' . |
318
|
|
|
'from tbl_filter_accounts ' . |
319
|
|
|
'where filter_id = ' . $filter['filter_id'] . ' and filter_flag = ' . FILTER_FLAG_CREATED_BY . ')'); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
View Code Duplication |
if ($filter['filter_flags'] & FILTER_FLAG_ASSIGNED_TO) |
|
|
|
|
323
|
|
|
{ |
324
|
|
|
array_push($clause_select, 'r.responsible_id'); |
325
|
|
|
array_push($clause_filter, |
326
|
|
|
'r.responsible_id in ' . |
327
|
|
|
'(select account_id ' . |
328
|
|
|
'from tbl_filter_accounts ' . |
329
|
|
|
'where filter_id = ' . $filter['filter_id'] . ' and filter_flag = ' . FILTER_FLAG_ASSIGNED_TO . ')'); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
if ($filter['filter_flags'] & FILTER_FLAG_UNASSIGNED) |
333
|
|
|
{ |
334
|
|
|
array_push($clause_select, 'r.responsible_id'); |
335
|
|
|
array_push($clause_filter, 'r.responsible_id is null'); |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
if (($filter['filter_type'] != FILTER_TYPE_SEL_STATES) && |
339
|
|
|
($filter['filter_flags'] & FILTER_FLAG_UNCLOSED)) |
340
|
|
|
{ |
341
|
|
|
array_push($clause_filter, 'r.closure_time is null'); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
if ($filter['filter_flags'] & FILTER_FLAG_POSTPONED) |
345
|
|
|
{ |
346
|
|
|
array_push($clause_filter, 'r.postpone_time > ' . $time); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
if ($filter['filter_flags'] & FILTER_FLAG_ACTIVE) |
350
|
|
|
{ |
351
|
|
|
array_push($clause_filter, 'r.postpone_time <=' . $time); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
if ($filter['filter_type'] == FILTER_TYPE_ALL_STATES || |
355
|
|
|
$filter['filter_type'] == FILTER_TYPE_SEL_STATES) |
356
|
|
|
{ |
357
|
|
|
$rs2 = dal_query('filters/ftlist.sql', $filter['filter_id']); |
358
|
|
|
|
359
|
|
|
while (($row = $rs2->fetch())) |
360
|
|
|
{ |
361
|
|
|
array_push($clause_filter, |
362
|
|
|
'r.record_id in ' . |
363
|
|
|
'(select record_id ' . |
364
|
|
|
'from tbl_events ' . |
365
|
|
|
'where (event_type = ' . EVENT_RECORD_CREATED . ' or event_type = ' . EVENT_RECORD_STATE_CHANGED . ') and ' . |
366
|
|
|
'event_time >= ' . $row['date1'] . ' and ' . |
367
|
|
|
'event_time <= ' . $row['date2'] . ' and ' . |
368
|
|
|
'event_param = ' . $row['state_id'] . ')'); |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
$rs2 = dal_query('filters/fflist.sql', $filter['filter_id']); |
372
|
|
|
|
373
|
|
|
while (($row = $rs2->fetch())) |
374
|
|
|
{ |
375
|
|
|
switch ($row['field_type']) |
376
|
|
|
{ |
377
|
|
|
case FIELD_TYPE_CHECKBOX: |
378
|
|
|
case FIELD_TYPE_LIST: |
379
|
|
|
case FIELD_TYPE_RECORD: |
380
|
|
|
|
381
|
|
|
$value = (is_null($row['param1']) |
382
|
|
|
? 'fv.value_id is null' |
383
|
|
|
: 'fv.value_id = ' . $row['param1']); |
384
|
|
|
|
385
|
|
|
array_push($clause_filter, |
386
|
|
|
'r.record_id in ' . |
387
|
|
|
'(select e.record_id ' . |
388
|
|
|
'from tbl_events e, tbl_field_values fv ' . |
389
|
|
|
'where fv.event_id = e.event_id and ' . |
390
|
|
|
'fv.field_id = ' . $row['field_id'] . ' and ' . |
391
|
|
|
$value . ' and ' . |
392
|
|
|
'fv.is_latest = 1)'); |
393
|
|
|
|
394
|
|
|
break; |
395
|
|
|
|
396
|
|
|
case FIELD_TYPE_NUMBER: |
397
|
|
|
case FIELD_TYPE_DATE: |
398
|
|
|
case FIELD_TYPE_DURATION: |
399
|
|
|
|
400
|
|
|
$range = (is_null($row['param1']) && is_null($row['param2']) ? 'fv.value_id is null and ' : NULL); |
401
|
|
|
|
402
|
|
|
if (!is_null($row['param1'])) |
403
|
|
|
{ |
404
|
|
|
$range .= 'fv.value_id >= ' . $row['param1'] . ' and '; |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
if (!is_null($row['param2'])) |
408
|
|
|
{ |
409
|
|
|
$range .= 'fv.value_id <= ' . $row['param2'] . ' and '; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
array_push($clause_filter, |
413
|
|
|
'r.record_id in ' . |
414
|
|
|
'(select e.record_id ' . |
415
|
|
|
'from tbl_events e, tbl_field_values fv ' . |
416
|
|
|
'where fv.event_id = e.event_id and ' . |
417
|
|
|
'fv.field_id = ' . $row['field_id'] . ' and ' . |
418
|
|
|
$range . |
419
|
|
|
'fv.is_latest = 1)'); |
420
|
|
|
|
421
|
|
|
break; |
422
|
|
|
|
423
|
|
|
case FIELD_TYPE_FLOAT: |
424
|
|
|
|
425
|
|
|
$range = (is_null($row['param1']) && is_null($row['param2']) ? 'fv.value_id is null and ' : NULL); |
426
|
|
|
|
427
|
|
|
if (!is_null($row['param1'])) |
428
|
|
|
{ |
429
|
|
|
$range .= 'fl1.float_value >= fl2.float_value and '; |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
if (!is_null($row['param2'])) |
433
|
|
|
{ |
434
|
|
|
$range .= 'fl1.float_value <= fl3.float_value and '; |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
array_push($clause_filter, |
438
|
|
|
'r.record_id in ' . |
439
|
|
|
'(select e.record_id ' . |
440
|
|
|
'from tbl_events e, tbl_field_values fv, tbl_float_values fl1, tbl_float_values fl2, tbl_float_values fl3 ' . |
441
|
|
|
'where fv.event_id = e.event_id and ' . |
442
|
|
|
'fv.field_id = ' . $row['field_id'] . ' and ' . |
443
|
|
|
'fv.value_id = fl1.value_id and ' . |
444
|
|
|
$range . |
445
|
|
|
'fl2.value_id = ' . $row['param1'] . ' and ' . |
446
|
|
|
'fl3.value_id = ' . $row['param2'] . ' and ' . |
447
|
|
|
'fv.is_latest = 1)'); |
448
|
|
|
|
449
|
|
|
break; |
450
|
|
|
|
451
|
|
View Code Duplication |
case FIELD_TYPE_STRING: |
|
|
|
|
452
|
|
|
|
453
|
|
|
if (is_null($row['param1'])) |
454
|
|
|
{ |
455
|
|
|
array_push($clause_filter, |
456
|
|
|
'r.record_id in ' . |
457
|
|
|
'(select e.record_id ' . |
458
|
|
|
'from tbl_events e, tbl_field_values fv ' . |
459
|
|
|
'where fv.event_id = e.event_id and ' . |
460
|
|
|
'fv.field_id = ' . $row['field_id'] . ' and ' . |
461
|
|
|
'fv.value_id is null and ' . |
462
|
|
|
'fv.is_latest = 1)'); |
463
|
|
|
} |
464
|
|
|
else |
465
|
|
|
{ |
466
|
|
|
switch (DATABASE_DRIVER) |
467
|
|
|
{ |
468
|
|
|
case DRIVER_MYSQL50: |
469
|
|
|
$concat = "concat('%', sf.string_value, '%')"; |
470
|
|
|
break; |
471
|
|
|
case DRIVER_ORACLE9: |
472
|
|
|
$concat = "concat(concat('%', sf.string_value), '%')"; |
473
|
|
|
break; |
474
|
|
|
case DRIVER_MSSQL2K: |
475
|
|
|
$concat = "'%' + sf.string_value + '%'"; |
476
|
|
|
break; |
477
|
|
|
case DRIVER_PGSQL80: |
478
|
|
|
$concat = "'%' || sf.string_value || '%'"; |
479
|
|
|
break; |
480
|
|
|
default: ; // nop |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
array_push($clause_filter, |
484
|
|
|
'r.record_id in ' . |
485
|
|
|
'(select e.record_id ' . |
486
|
|
|
'from tbl_events e, tbl_field_values fv, tbl_string_values sv, tbl_string_values sf ' . |
487
|
|
|
'where fv.event_id = e.event_id and ' . |
488
|
|
|
'fv.field_id = ' . $row['field_id'] . ' and ' . |
489
|
|
|
'fv.value_id = sv.value_id and ' . |
490
|
|
|
'sf.value_id = ' . $row['param1'] . ' and ' . |
491
|
|
|
'sv.string_value like ' . $concat . ' and ' . |
492
|
|
|
'fv.is_latest = 1)'); |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
break; |
496
|
|
|
|
497
|
|
View Code Duplication |
case FIELD_TYPE_MULTILINED: |
|
|
|
|
498
|
|
|
|
499
|
|
|
if (is_null($row['param1'])) |
500
|
|
|
{ |
501
|
|
|
array_push($clause_filter, |
502
|
|
|
'r.record_id in ' . |
503
|
|
|
'(select e.record_id ' . |
504
|
|
|
'from tbl_events e, tbl_field_values fv ' . |
505
|
|
|
'where fv.event_id = e.event_id and ' . |
506
|
|
|
'fv.field_id = ' . $row['field_id'] . ' and ' . |
507
|
|
|
'fv.value_id is null and ' . |
508
|
|
|
'fv.is_latest = 1)'); |
509
|
|
|
} |
510
|
|
|
else |
511
|
|
|
{ |
512
|
|
|
switch (DATABASE_DRIVER) |
513
|
|
|
{ |
514
|
|
|
case DRIVER_MYSQL50: |
515
|
|
|
$concat = "concat('%', sf.string_value, '%')"; |
516
|
|
|
break; |
517
|
|
|
case DRIVER_ORACLE9: |
518
|
|
|
$concat = "concat(concat('%', sf.string_value), '%')"; |
519
|
|
|
break; |
520
|
|
|
case DRIVER_MSSQL2K: |
521
|
|
|
$concat = "'%' + sf.string_value + '%'"; |
522
|
|
|
break; |
523
|
|
|
case DRIVER_PGSQL80: |
524
|
|
|
$concat = "'%' || sf.string_value || '%'"; |
525
|
|
|
break; |
526
|
|
|
default: ; // nop |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
array_push($clause_filter, |
530
|
|
|
'r.record_id in ' . |
531
|
|
|
'(select e.record_id ' . |
532
|
|
|
'from tbl_events e, tbl_field_values fv, tbl_text_values tv, tbl_string_values sf ' . |
533
|
|
|
'where fv.event_id = e.event_id and ' . |
534
|
|
|
'fv.field_id = ' . $row['field_id'] . ' and ' . |
535
|
|
|
'fv.value_id = tv.value_id and ' . |
536
|
|
|
'sf.value_id = ' . $row['param1'] . ' and ' . |
537
|
|
|
'tv.text_value like ' . $concat . ' and ' . |
538
|
|
|
'fv.is_latest = 1)'); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
break; |
542
|
|
|
} |
543
|
|
|
} |
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
array_push($filters, implode(' and ', array_unique($clause_filter))); |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
if (count($filters) != 0) |
550
|
|
|
{ |
551
|
|
|
array_push($clause_where, '(' . implode(' or ', array_unique($filters)) . ')'); |
552
|
|
|
} |
553
|
|
|
} |
554
|
|
|
|
555
|
|
|
// Create basic query. |
556
|
|
|
|
557
|
|
|
$sql = 'select ' . implode(', ', array_unique($clause_select)) . |
558
|
|
|
' from ' . implode(', ', array_unique($clause_from)) . |
559
|
|
|
', ' . implode(' ', array_unique($clause_join)) . |
560
|
|
|
' where ' . implode(' and ', array_unique($clause_where)); |
561
|
|
|
|
562
|
|
|
$clause_select = array('r.*'); |
563
|
|
|
$clause_select = array('r.record_id', |
564
|
|
|
'r.subject', |
565
|
|
|
'r.responsible_id', |
566
|
|
|
'r.creator_id', |
567
|
|
|
'r.creation_time', |
568
|
|
|
'r.change_time', |
569
|
|
|
'r.closure_time', |
570
|
|
|
'r.postpone_time', |
571
|
|
|
'r.project_name', |
572
|
|
|
'r.template_name', |
573
|
|
|
'r.template_prefix', |
574
|
|
|
'r.critical_age', |
575
|
|
|
'r.state_name', |
576
|
|
|
'r.state_abbr', |
577
|
|
|
'r.read_time'); |
578
|
|
|
$clause_from = array(); |
579
|
|
|
$clause_join = array(); |
580
|
|
|
$clause_where = array(); |
581
|
|
|
$clause_order = array(); |
582
|
|
|
|
583
|
|
|
// SQL condition to check that current user is allowed to read the field. |
584
|
|
|
|
585
|
|
|
$sql_field_perms = <<<SQL |
586
|
|
|
|
587
|
|
|
f.field_id in (select f.field_id |
588
|
|
|
from |
589
|
|
|
tbl_group_perms gp, |
590
|
|
|
tbl_membership ms, |
591
|
|
|
tbl_field_perms fp, |
592
|
|
|
tbl_fields f |
593
|
|
|
where |
594
|
|
|
fp.field_id = f.field_id and |
595
|
|
|
fp.group_id = gp.group_id and |
596
|
|
|
ms.group_id = gp.group_id and |
597
|
|
|
ms.account_id = {$_SESSION[VAR_USERID]} and |
598
|
|
|
fp.perms = 1) |
599
|
|
|
|
600
|
|
|
or r.creator_id = {$_SESSION[VAR_USERID]} and |
601
|
|
|
f.field_id in (select f.field_id |
602
|
|
|
from tbl_fields f |
603
|
|
|
where f.author_perm >= 1) |
604
|
|
|
|
605
|
|
|
or r.responsible_id = {$_SESSION[VAR_USERID]} and |
606
|
|
|
f.field_id in (select f.field_id |
607
|
|
|
from tbl_fields f |
608
|
|
|
where f.responsible_perm >= 1) |
609
|
|
|
|
610
|
|
|
or f.field_id in (select f.field_id |
611
|
|
|
from tbl_fields f |
612
|
|
|
where f.registered_perm >= 1 or f.guest_access = 1) |
613
|
|
|
SQL; |
614
|
|
|
|
615
|
|
|
// Generate columns of the current view. |
616
|
|
|
|
617
|
|
|
foreach ($columns as $i => $column) |
618
|
|
|
{ |
619
|
|
|
$i += 1; |
620
|
|
|
|
621
|
|
|
switch ($column['column_type']) |
622
|
|
|
{ |
623
|
|
View Code Duplication |
case COLUMN_TYPE_ID: |
|
|
|
|
624
|
|
|
|
625
|
|
|
array_push($clause_select, 'r.template_prefix'); |
626
|
|
|
|
627
|
|
|
if ($i == $sort) |
628
|
|
|
{ |
629
|
|
|
array_push($clause_order, 'record_id asc'); |
630
|
|
|
} |
631
|
|
|
elseif (-$i == $sort) |
632
|
|
|
{ |
633
|
|
|
array_push($clause_order, 'record_id desc'); |
634
|
|
|
} |
635
|
|
|
|
636
|
|
|
break; |
637
|
|
|
|
638
|
|
View Code Duplication |
case COLUMN_TYPE_STATE_ABBR: |
|
|
|
|
639
|
|
|
|
640
|
|
|
array_push($clause_select, 'r.state_abbr'); |
641
|
|
|
|
642
|
|
|
if ($i == $sort) |
643
|
|
|
{ |
644
|
|
|
array_push($clause_order, 'state_abbr asc'); |
645
|
|
|
} |
646
|
|
|
elseif (-$i == $sort) |
647
|
|
|
{ |
648
|
|
|
array_push($clause_order, 'state_abbr desc'); |
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
break; |
652
|
|
|
|
653
|
|
View Code Duplication |
case COLUMN_TYPE_PROJECT: |
|
|
|
|
654
|
|
|
|
655
|
|
|
array_push($clause_select, 'r.project_name'); |
656
|
|
|
|
657
|
|
|
if ($i == $sort) |
658
|
|
|
{ |
659
|
|
|
array_push($clause_order, 'project_name asc'); |
660
|
|
|
} |
661
|
|
|
elseif (-$i == $sort) |
662
|
|
|
{ |
663
|
|
|
array_push($clause_order, 'project_name desc'); |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
break; |
667
|
|
|
|
668
|
|
View Code Duplication |
case COLUMN_TYPE_SUBJECT: |
|
|
|
|
669
|
|
|
|
670
|
|
|
array_push($clause_select, 'r.subject'); |
671
|
|
|
|
672
|
|
|
if ($i == $sort) |
673
|
|
|
{ |
674
|
|
|
array_push($clause_order, 'subject asc'); |
675
|
|
|
} |
676
|
|
|
elseif (-$i == $sort) |
677
|
|
|
{ |
678
|
|
|
array_push($clause_order, 'subject desc'); |
679
|
|
|
} |
680
|
|
|
|
681
|
|
|
break; |
682
|
|
|
|
683
|
|
View Code Duplication |
case COLUMN_TYPE_AUTHOR: |
|
|
|
|
684
|
|
|
|
685
|
|
|
array_push($clause_select, 'ac.fullname as author_fullname'); |
686
|
|
|
array_push($clause_join, 'left outer join tbl_accounts ac on ac.account_id = r.creator_id'); |
687
|
|
|
|
688
|
|
|
if ($i == $sort) |
689
|
|
|
{ |
690
|
|
|
array_push($clause_order, 'author_fullname asc'); |
691
|
|
|
} |
692
|
|
|
elseif (-$i == $sort) |
693
|
|
|
{ |
694
|
|
|
array_push($clause_order, 'author_fullname desc'); |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
break; |
698
|
|
|
|
699
|
|
View Code Duplication |
case COLUMN_TYPE_RESPONSIBLE: |
|
|
|
|
700
|
|
|
|
701
|
|
|
array_push($clause_select, 'ar.fullname as responsible_fullname'); |
702
|
|
|
array_push($clause_join, 'left outer join tbl_accounts ar on ar.account_id = r.responsible_id'); |
703
|
|
|
|
704
|
|
|
if ($i == $sort) |
705
|
|
|
{ |
706
|
|
|
array_push($clause_order, 'responsible_fullname asc'); |
707
|
|
|
} |
708
|
|
|
elseif (-$i == $sort) |
709
|
|
|
{ |
710
|
|
|
array_push($clause_order, 'responsible_fullname desc'); |
711
|
|
|
} |
712
|
|
|
|
713
|
|
|
break; |
714
|
|
|
|
715
|
|
View Code Duplication |
case COLUMN_TYPE_LAST_EVENT: |
|
|
|
|
716
|
|
|
|
717
|
|
|
if ($i == $sort) |
718
|
|
|
{ |
719
|
|
|
array_push($clause_order, 'change_time asc'); |
720
|
|
|
} |
721
|
|
|
elseif (-$i == $sort) |
722
|
|
|
{ |
723
|
|
|
array_push($clause_order, 'change_time desc'); |
724
|
|
|
} |
725
|
|
|
|
726
|
|
|
break; |
727
|
|
|
|
728
|
|
View Code Duplication |
case COLUMN_TYPE_AGE: |
|
|
|
|
729
|
|
|
|
730
|
|
|
array_push($clause_select, '(' . $time . ' - r.creation_time) as opened_age'); |
731
|
|
|
array_push($clause_select, '(r.closure_time - r.creation_time) as closed_age'); |
732
|
|
|
|
733
|
|
|
if ($i == $sort) |
734
|
|
|
{ |
735
|
|
|
array_push($clause_order, 'closed_age asc'); |
736
|
|
|
array_push($clause_order, 'opened_age asc'); |
737
|
|
|
} |
738
|
|
|
elseif (-$i == $sort) |
739
|
|
|
{ |
740
|
|
|
array_push($clause_order, 'closed_age desc'); |
741
|
|
|
array_push($clause_order, 'opened_age desc'); |
742
|
|
|
} |
743
|
|
|
|
744
|
|
|
break; |
745
|
|
|
|
746
|
|
View Code Duplication |
case COLUMN_TYPE_CREATION_DATE: |
|
|
|
|
747
|
|
|
|
748
|
|
|
array_push($clause_select, 'r.creation_time'); |
749
|
|
|
|
750
|
|
|
if ($i == $sort) |
751
|
|
|
{ |
752
|
|
|
array_push($clause_order, 'creation_time asc'); |
753
|
|
|
} |
754
|
|
|
elseif (-$i == $sort) |
755
|
|
|
{ |
756
|
|
|
array_push($clause_order, 'creation_time desc'); |
757
|
|
|
} |
758
|
|
|
|
759
|
|
|
break; |
760
|
|
|
|
761
|
|
View Code Duplication |
case COLUMN_TYPE_TEMPLATE: |
|
|
|
|
762
|
|
|
|
763
|
|
|
array_push($clause_select, 'r.template_name'); |
764
|
|
|
|
765
|
|
|
if ($i == $sort) |
766
|
|
|
{ |
767
|
|
|
array_push($clause_order, 'template_name asc'); |
768
|
|
|
} |
769
|
|
|
elseif (-$i == $sort) |
770
|
|
|
{ |
771
|
|
|
array_push($clause_order, 'template_name desc'); |
772
|
|
|
} |
773
|
|
|
|
774
|
|
|
break; |
775
|
|
|
|
776
|
|
View Code Duplication |
case COLUMN_TYPE_STATE_NAME: |
|
|
|
|
777
|
|
|
|
778
|
|
|
array_push($clause_select, 'r.state_name'); |
779
|
|
|
|
780
|
|
|
if ($i == $sort) |
781
|
|
|
{ |
782
|
|
|
array_push($clause_order, 'state_name asc'); |
783
|
|
|
} |
784
|
|
|
elseif (-$i == $sort) |
785
|
|
|
{ |
786
|
|
|
array_push($clause_order, 'state_name desc'); |
787
|
|
|
} |
788
|
|
|
|
789
|
|
|
break; |
790
|
|
|
|
791
|
|
View Code Duplication |
case COLUMN_TYPE_LAST_STATE: |
|
|
|
|
792
|
|
|
|
793
|
|
|
array_push($clause_select, 'st.state_time'); |
794
|
|
|
array_push($clause_from, '(select record_id, max(event_time) as state_time' . |
795
|
|
|
' from tbl_events' . |
796
|
|
|
' where event_type = 1 or event_type = 4' . |
797
|
|
|
' group by record_id) st'); |
798
|
|
|
array_push($clause_where, 'r.record_id = st.record_id'); |
799
|
|
|
|
800
|
|
|
if ($i == $sort) |
801
|
|
|
{ |
802
|
|
|
array_push($clause_order, 'state_time asc'); |
803
|
|
|
} |
804
|
|
|
elseif (-$i == $sort) |
805
|
|
|
{ |
806
|
|
|
array_push($clause_order, 'state_time desc'); |
807
|
|
|
} |
808
|
|
|
|
809
|
|
|
break; |
810
|
|
|
|
811
|
|
View Code Duplication |
case COLUMN_TYPE_FLOAT: |
|
|
|
|
812
|
|
|
|
813
|
|
|
array_push($clause_select, "v{$column['column_id']}.value{$column['column_id']}"); |
814
|
|
|
|
815
|
|
|
array_push($clause_join, |
816
|
|
|
"left outer join " . |
817
|
|
|
"(select r.record_id, flv.float_value as value{$column['column_id']} " . |
818
|
|
|
"from tbl_records r, tbl_states s, tbl_fields f, tbl_events e, tbl_field_values fv " . |
819
|
|
|
"left outer join tbl_float_values flv on fv.value_id = flv.value_id " . |
820
|
|
|
"where r.record_id = e.record_id and s.state_id = f.state_id and s.state_name = '{$column['state_name']}' and f.field_id = fv.field_id and f.field_name = '{$column['field_name']}' and f.field_type = " . FIELD_TYPE_FLOAT . " and e.event_id = fv.event_id and fv.is_latest = 1 and ({$sql_field_perms})) v{$column['column_id']} " . |
821
|
|
|
"on r.record_id = v{$column['column_id']}.record_id"); |
822
|
|
|
|
823
|
|
|
if ($i == $sort) |
824
|
|
|
{ |
825
|
|
|
array_push($clause_order, "value{$column['column_id']} asc"); |
826
|
|
|
} |
827
|
|
|
elseif (-$i == $sort) |
828
|
|
|
{ |
829
|
|
|
array_push($clause_order, "value{$column['column_id']} desc"); |
830
|
|
|
} |
831
|
|
|
|
832
|
|
|
break; |
833
|
|
|
|
834
|
|
View Code Duplication |
case COLUMN_TYPE_STRING: |
|
|
|
|
835
|
|
|
|
836
|
|
|
array_push($clause_select, "v{$column['column_id']}.value{$column['column_id']}"); |
837
|
|
|
|
838
|
|
|
array_push($clause_join, |
839
|
|
|
"left outer join " . |
840
|
|
|
"(select r.record_id, sv.string_value as value{$column['column_id']} " . |
841
|
|
|
"from tbl_records r, tbl_states s, tbl_fields f, tbl_events e, tbl_field_values fv " . |
842
|
|
|
"left outer join tbl_string_values sv on fv.value_id = sv.value_id " . |
843
|
|
|
"where r.record_id = e.record_id and s.state_id = f.state_id and s.state_name = '{$column['state_name']}' and f.field_id = fv.field_id and f.field_name = '{$column['field_name']}' and f.field_type = " . FIELD_TYPE_STRING . " and e.event_id = fv.event_id and fv.is_latest = 1 and ({$sql_field_perms})) v{$column['column_id']} " . |
844
|
|
|
"on r.record_id = v{$column['column_id']}.record_id"); |
845
|
|
|
|
846
|
|
|
if ($i == $sort) |
847
|
|
|
{ |
848
|
|
|
array_push($clause_order, "value{$column['column_id']} asc"); |
849
|
|
|
} |
850
|
|
|
elseif (-$i == $sort) |
851
|
|
|
{ |
852
|
|
|
array_push($clause_order, "value{$column['column_id']} desc"); |
853
|
|
|
} |
854
|
|
|
|
855
|
|
|
break; |
856
|
|
|
|
857
|
|
|
case COLUMN_TYPE_MULTILINED: |
858
|
|
|
|
859
|
|
|
$txtval = (DATABASE_DRIVER == DRIVER_MSSQL2K ? 'substring(tv.text_value, 1, 4000)' : 'substr(tv.text_value, 1, 4000)'); |
860
|
|
|
|
861
|
|
|
if (DATABASE_DRIVER == DRIVER_ORACLE9) |
862
|
|
|
{ |
863
|
|
|
array_push($clause_select, "to_char(v{$column['column_id']}.value{$column['column_id']}) as \"value{$column['column_id']}\""); |
864
|
|
|
} |
865
|
|
|
else |
866
|
|
|
{ |
867
|
|
|
array_push($clause_select, "v{$column['column_id']}.value{$column['column_id']}"); |
868
|
|
|
} |
869
|
|
|
|
870
|
|
|
array_push($clause_join, |
871
|
|
|
"left outer join " . |
872
|
|
|
"(select r.record_id, {$txtval} as value{$column['column_id']} " . |
873
|
|
|
"from tbl_records r, tbl_states s, tbl_fields f, tbl_events e, tbl_field_values fv " . |
874
|
|
|
"left outer join tbl_text_values tv on fv.value_id = tv.value_id " . |
875
|
|
|
"where r.record_id = e.record_id and s.state_id = f.state_id and s.state_name = '{$column['state_name']}' and f.field_id = fv.field_id and f.field_name = '{$column['field_name']}' and f.field_type = " . FIELD_TYPE_MULTILINED . " and e.event_id = fv.event_id and fv.is_latest = 1 and ({$sql_field_perms})) v{$column['column_id']} " . |
876
|
|
|
"on r.record_id = v{$column['column_id']}.record_id"); |
877
|
|
|
|
878
|
|
|
if ($i == $sort) |
879
|
|
|
{ |
880
|
|
|
array_push($clause_order, DATABASE_DRIVER == DRIVER_ORACLE9 |
881
|
|
|
? "to_char(value{$column['column_id']}) asc" |
882
|
|
|
: "value{$column['column_id']} asc"); |
883
|
|
|
} |
884
|
|
|
elseif (-$i == $sort) |
885
|
|
|
{ |
886
|
|
|
array_push($clause_order, DATABASE_DRIVER == DRIVER_ORACLE9 |
887
|
|
|
? "to_char(value{$column['column_id']}) desc" |
888
|
|
|
: "value{$column['column_id']} desc"); |
889
|
|
|
} |
890
|
|
|
|
891
|
|
|
break; |
892
|
|
|
|
893
|
|
View Code Duplication |
case COLUMN_TYPE_LIST_STRING: |
|
|
|
|
894
|
|
|
|
895
|
|
|
array_push($clause_select, "v{$column['column_id']}.value{$column['column_id']}"); |
896
|
|
|
|
897
|
|
|
array_push($clause_join, |
898
|
|
|
"left outer join " . |
899
|
|
|
"(select r.record_id, lv.str_value as value{$column['column_id']} " . |
900
|
|
|
"from tbl_records r, tbl_states s, tbl_fields f, tbl_events e, tbl_field_values fv " . |
901
|
|
|
"left outer join tbl_list_values lv on fv.field_id = lv.field_id and fv.value_id = lv.int_value " . |
902
|
|
|
"where r.record_id = e.record_id and s.state_id = f.state_id and s.state_name = '{$column['state_name']}' and f.field_id = fv.field_id and f.field_name = '{$column['field_name']}' and f.field_type = " . FIELD_TYPE_LIST . " and e.event_id = fv.event_id and fv.is_latest = 1 and ({$sql_field_perms})) v{$column['column_id']} " . |
903
|
|
|
"on r.record_id = v{$column['column_id']}.record_id"); |
904
|
|
|
|
905
|
|
|
if ($i == $sort) |
906
|
|
|
{ |
907
|
|
|
array_push($clause_order, "value{$column['column_id']} asc"); |
908
|
|
|
} |
909
|
|
|
elseif (-$i == $sort) |
910
|
|
|
{ |
911
|
|
|
array_push($clause_order, "value{$column['column_id']} desc"); |
912
|
|
|
} |
913
|
|
|
|
914
|
|
|
break; |
915
|
|
|
|
916
|
|
|
case COLUMN_TYPE_NUMBER: |
917
|
|
|
case COLUMN_TYPE_CHECKBOX: |
918
|
|
|
case COLUMN_TYPE_LIST_NUMBER: |
919
|
|
|
case COLUMN_TYPE_RECORD: |
920
|
|
|
case COLUMN_TYPE_DATE: |
921
|
|
|
case COLUMN_TYPE_DURATION: |
922
|
|
|
|
923
|
|
|
$types = array |
924
|
|
|
( |
925
|
|
|
COLUMN_TYPE_NUMBER => FIELD_TYPE_NUMBER, |
926
|
|
|
COLUMN_TYPE_CHECKBOX => FIELD_TYPE_CHECKBOX, |
927
|
|
|
COLUMN_TYPE_LIST_NUMBER => FIELD_TYPE_LIST, |
928
|
|
|
COLUMN_TYPE_RECORD => FIELD_TYPE_RECORD, |
929
|
|
|
COLUMN_TYPE_DATE => FIELD_TYPE_DATE, |
930
|
|
|
COLUMN_TYPE_DURATION => FIELD_TYPE_DURATION, |
931
|
|
|
); |
932
|
|
|
|
933
|
|
|
array_push($clause_select, "v{$column['column_id']}.value{$column['column_id']}"); |
934
|
|
|
|
935
|
|
|
array_push($clause_join, |
936
|
|
|
"left outer join " . |
937
|
|
|
"(select r.record_id, fv.value_id as value{$column['column_id']} " . |
938
|
|
|
"from tbl_records r, tbl_states s, tbl_fields f, tbl_events e, tbl_field_values fv " . |
939
|
|
|
"where r.record_id = e.record_id and s.state_id = f.state_id and s.state_name = '{$column['state_name']}' and f.field_id = fv.field_id and f.field_name = '{$column['field_name']}' and f.field_type = {$types[$column['column_type']]} and e.event_id = fv.event_id and fv.is_latest = 1 and ({$sql_field_perms})) v{$column['column_id']} " . |
940
|
|
|
"on r.record_id = v{$column['column_id']}.record_id"); |
941
|
|
|
|
942
|
|
|
if ($i == $sort) |
943
|
|
|
{ |
944
|
|
|
array_push($clause_order, "value{$column['column_id']} asc"); |
945
|
|
|
} |
946
|
|
|
elseif (-$i == $sort) |
947
|
|
|
{ |
948
|
|
|
array_push($clause_order, "value{$column['column_id']} desc"); |
949
|
|
|
} |
950
|
|
|
|
951
|
|
|
break; |
952
|
|
|
|
953
|
|
|
default: |
954
|
|
|
debug_write_log(DEBUG_WARNING, '[records_list] Unknown column type = ' . $column['column_type']); |
955
|
|
|
} |
956
|
|
|
} |
957
|
|
|
|
958
|
|
|
// Add default sorting. |
959
|
|
|
|
960
|
|
|
if ($sort < 0) |
961
|
|
|
{ |
962
|
|
|
array_push($clause_order, 'record_id desc'); |
963
|
|
|
} |
964
|
|
|
else |
965
|
|
|
{ |
966
|
|
|
array_push($clause_order, 'record_id asc'); |
967
|
|
|
} |
968
|
|
|
|
969
|
|
|
// Bring it all together. |
970
|
|
|
|
971
|
|
|
array_push($clause_from, "({$sql}) r"); |
972
|
|
|
|
973
|
|
|
$sql = 'select ' . implode(', ', array_unique($clause_select)) . |
974
|
|
|
' from ' . implode(', ', array_unique($clause_from)) . |
975
|
|
|
' ' . implode(' ', array_unique($clause_join)); |
976
|
|
|
|
977
|
|
|
if (count($clause_where) != 0) |
978
|
|
|
{ |
979
|
|
|
$sql .= ' where ' . implode(' and ', array_unique($clause_where)); |
980
|
|
|
} |
981
|
|
|
|
982
|
|
|
$sql .= ' order by ' . implode(', ', array_unique($clause_order)); |
983
|
|
|
|
984
|
|
|
return new CRecordset($sql); |
985
|
|
|
} |
986
|
|
|
|
987
|
|
|
/** |
988
|
|
|
* Returns {@link CRecordset DAL recordset} which contains number of created records per week for specified project. |
989
|
|
|
* Each row of returned recordset contains two fields: |
990
|
|
|
* <ul> |
991
|
|
|
* <li><b>week</b> - number of week after {@link http://en.wikipedia.org/wiki/Unix_time Unix Epoch}.</li> |
992
|
|
|
* <li><b>amount</b> - number of records, created during this week</li> |
993
|
|
|
* </ul> |
994
|
|
|
* |
995
|
|
|
* @param int $id ID of project which records should be counted. |
996
|
|
|
* @return CRecordset Recordset with list of counts. |
997
|
|
|
*/ |
998
|
|
View Code Duplication |
function record_opened ($id) |
|
|
|
|
999
|
|
|
{ |
1000
|
|
|
debug_write_log(DEBUG_TRACE, '[record_opened]'); |
1001
|
|
|
debug_write_log(DEBUG_DUMP, '[record_opened] $id = ' . $id); |
1002
|
|
|
|
1003
|
|
|
return dal_query('records/opened.sql', $id, date('Z'), (DATABASE_DRIVER == DRIVER_ORACLE9 ? 'ceil' : 'ceiling')); |
1004
|
|
|
} |
1005
|
|
|
|
1006
|
|
|
/** |
1007
|
|
|
* Returns {@link CRecordset DAL recordset} which contains number of closed records per week for specified project. |
1008
|
|
|
* Each row of returned recordset contains two fields: |
1009
|
|
|
* <ul> |
1010
|
|
|
* <li><b>week</b> - number of week after {@link http://en.wikipedia.org/wiki/Unix_time Unix Epoch}.</li> |
1011
|
|
|
* <li><b>amount</b> - number of records, closed during this week</li> |
1012
|
|
|
* </ul> |
1013
|
|
|
* |
1014
|
|
|
* @param int $id ID of project which records should be counted. |
1015
|
|
|
* @return CRecordset Recordset with list of counts. |
1016
|
|
|
*/ |
1017
|
|
View Code Duplication |
function record_closed ($id) |
|
|
|
|
1018
|
|
|
{ |
1019
|
|
|
debug_write_log(DEBUG_TRACE, '[record_closed]'); |
1020
|
|
|
debug_write_log(DEBUG_DUMP, '[record_closed] $id = ' . $id); |
1021
|
|
|
|
1022
|
|
|
return dal_query('records/closed.sql', $id, date('Z'), (DATABASE_DRIVER == DRIVER_ORACLE9 ? 'ceil' : 'ceiling')); |
1023
|
|
|
} |
1024
|
|
|
|
1025
|
|
|
/** |
1026
|
|
|
* Validates record information (including all custom fields) before creation, modification, or changing state. |
1027
|
|
|
* |
1028
|
|
|
* @param int $operation Code of operation: |
1029
|
|
|
* <ul> |
1030
|
|
|
* <li>{@link OPERATION_CREATE_RECORD} - new record is going to be created</li> |
1031
|
|
|
* <li>{@link OPERATION_MODIFY_RECORD} - record is going to be modified</li> |
1032
|
|
|
* <li>{@link OPERATION_CHANGE_STATE} - state of record is going to be changed</li> |
1033
|
|
|
* </ul> |
1034
|
|
|
* @param string $subject Subject of the record (ignored on state change). |
1035
|
|
|
* @param int $record_id Record ID (should be NULL on creation). |
1036
|
|
|
* @param int $state_id ID of new state (current on modification). |
1037
|
|
|
* @param int $creator_id Author of record (used only on modification, otherwise ignored). |
1038
|
|
|
* @param int $responsible_id Responsible of record (used only on modification, otherwise ignored). |
1039
|
|
|
* @return int Error code: |
1040
|
|
|
* <ul> |
1041
|
|
|
* <li>{@link NO_ERROR} - data are valid</li> |
1042
|
|
|
* <li>{@link ERROR_INCOMPLETE_FORM} - at least one of required field is empty</li> |
1043
|
|
|
* <li>{@link ERROR_INVALID_INTEGER_VALUE} - value of some custom field of {@link FIELD_TYPE_NUMBER}, {@link FIELD_TYPE_LIST}, or {@link FIELD_TYPE_RECORD} type is not an integer</li> |
1044
|
|
|
* <li>{@link ERROR_INTEGER_VALUE_OUT_OF_RANGE} - value of some custom field of {@link FIELD_TYPE_NUMBER} or {@link FIELD_TYPE_LIST} type is out of valid range</li> |
1045
|
|
|
* <li>{@link ERROR_VALUE_FAILS_REGEX_CHECK} - value of some custom field of {@link FIELD_TYPE_STRING} or {@link FIELD_TYPE_MULTILINED} type fails the custom PCRE check</li> |
1046
|
|
|
* <li>{@link ERROR_RECORD_NOT_FOUND} - value of some custom field of {@link FIELD_TYPE_RECORD} type is not an ID of existing record</li> |
1047
|
|
|
* <li>{@link ERROR_INVALID_DATE_VALUE} - value of some custom field of {@link FIELD_TYPE_DATE} type is not a valid date value</li> |
1048
|
|
|
* <li>{@link ERROR_DATE_VALUE_OUT_OF_RANGE} - value of some custom field of {@link FIELD_TYPE_DATE} type is out of valid range</li> |
1049
|
|
|
* <li>{@link ERROR_INVALID_TIME_VALUE} - value of some custom field of {@link FIELD_TYPE_DURATION} type is not a valid duration value</li> |
1050
|
|
|
* <li>{@link ERROR_TIME_VALUE_OUT_OF_RANGE} - value of some custom field of {@link FIELD_TYPE_DURATION} type is out of valid range</li> |
1051
|
|
|
* </ul> |
1052
|
|
|
*/ |
1053
|
|
|
function record_validate ($operation, $subject, $record_id, $state_id, $creator_id = 0, $responsible_id = 0) |
1054
|
|
|
{ |
1055
|
|
|
debug_write_log(DEBUG_TRACE, '[record_validate]'); |
1056
|
|
|
debug_write_log(DEBUG_DUMP, '[record_validate] $operation = ' . $operation); |
1057
|
|
|
debug_write_log(DEBUG_DUMP, '[record_validate] $subject = ' . $subject); |
1058
|
|
|
debug_write_log(DEBUG_DUMP, '[record_validate] $record_id = ' . $record_id); |
1059
|
|
|
debug_write_log(DEBUG_DUMP, '[record_validate] $state_id = ' . $state_id); |
1060
|
|
|
debug_write_log(DEBUG_DUMP, '[record_validate] $creator_id = ' . $creator_id); |
1061
|
|
|
debug_write_log(DEBUG_DUMP, '[record_validate] $responsible_id = ' . $responsible_id); |
1062
|
|
|
|
1063
|
|
|
// Check the subject. |
1064
|
|
|
if ($operation != OPERATION_CHANGE_STATE && |
1065
|
|
|
ustrlen($subject) == 0) |
1066
|
|
|
{ |
1067
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] At least one required field is empty.'); |
1068
|
|
|
return ERROR_INCOMPLETE_FORM; |
1069
|
|
|
} |
1070
|
|
|
|
1071
|
|
|
// Get the list of custom fields. |
1072
|
|
|
if ($operation != OPERATION_MODIFY_RECORD) |
1073
|
|
|
{ |
1074
|
|
|
$rs = dal_query('fields/list.sql', $state_id, 'field_order'); |
1075
|
|
|
} |
1076
|
|
|
else |
1077
|
|
|
{ |
1078
|
|
|
$rs = dal_query('records/flist.sql', |
1079
|
|
|
$record_id, |
1080
|
|
|
$state_id, |
1081
|
|
|
$creator_id, |
1082
|
|
|
is_null($responsible_id) ? 0 : $responsible_id, |
1083
|
|
|
$_SESSION[VAR_USERID], |
1084
|
|
|
FIELD_ALLOW_TO_WRITE); |
1085
|
|
|
} |
1086
|
|
|
|
1087
|
|
|
// Check value candidates of all fields. |
1088
|
|
|
// Values of all custom fields are passed to the function via $_REQUEST. |
1089
|
|
|
while (($row = $rs->fetch())) |
1090
|
|
|
{ |
1091
|
|
|
$name = 'field' . $row['field_id']; |
1092
|
|
|
$value = ($row['field_type'] == FIELD_TYPE_CHECKBOX ? isset($_REQUEST[$name]) : trim(try_request($name))); |
1093
|
|
|
|
1094
|
|
|
// Required custom fields must be filled in. |
1095
|
|
|
if ($row['is_required'] && |
1096
|
|
|
$row['field_type'] != FIELD_TYPE_CHECKBOX && |
1097
|
|
|
ustrlen($value) == 0) |
1098
|
|
|
{ |
1099
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] At least one required field is empty.'); |
1100
|
|
|
return ERROR_INCOMPLETE_FORM; |
1101
|
|
|
} |
1102
|
|
|
|
1103
|
|
|
// Check value candidate of this field in correspondence with its type and template configuration. |
1104
|
|
|
switch ($row['field_type']) |
1105
|
|
|
{ |
1106
|
|
|
case FIELD_TYPE_NUMBER: |
1107
|
|
|
|
1108
|
|
View Code Duplication |
if (ustrlen($value) != 0) |
|
|
|
|
1109
|
|
|
{ |
1110
|
|
|
if (!is_intvalue($value)) |
1111
|
|
|
{ |
1112
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Invalid integer value.'); |
1113
|
|
|
return ERROR_INVALID_INTEGER_VALUE; |
1114
|
|
|
} |
1115
|
|
|
|
1116
|
|
|
$intvalue = intval($value); |
1117
|
|
|
|
1118
|
|
|
if ($intvalue < $row['param1'] || |
1119
|
|
|
$intvalue > $row['param2']) |
1120
|
|
|
{ |
1121
|
|
|
$_SESSION['FIELD_NAME'] = $row['field_name']; |
1122
|
|
|
$_SESSION['MIN_FIELD_INTEGER'] = $row['param1']; |
1123
|
|
|
$_SESSION['MAX_FIELD_INTEGER'] = $row['param2']; |
1124
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Integer value is out of range.'); |
1125
|
|
|
return ERROR_INTEGER_VALUE_OUT_OF_RANGE; |
1126
|
|
|
} |
1127
|
|
|
} |
1128
|
|
|
|
1129
|
|
|
break; |
1130
|
|
|
|
1131
|
|
|
case FIELD_TYPE_FLOAT: |
1132
|
|
|
|
1133
|
|
|
if (ustrlen($value) != 0) |
1134
|
|
|
{ |
1135
|
|
|
if (!is_floatvalue($value)) |
1136
|
|
|
{ |
1137
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Invalid float value.'); |
1138
|
|
|
return ERROR_INVALID_FLOAT_VALUE; |
1139
|
|
|
} |
1140
|
|
|
|
1141
|
|
|
$minFieldFloat = value_find(FIELD_TYPE_FLOAT, $row['param1']); |
1142
|
|
|
$maxFieldFloat = value_find(FIELD_TYPE_FLOAT, $row['param2']); |
1143
|
|
|
|
1144
|
|
|
if (bccomp($value, $minFieldFloat) < 0 || bccomp($value, $maxFieldFloat) > 0) |
1145
|
|
|
{ |
1146
|
|
|
$_SESSION['FIELD_NAME'] = $row['field_name']; |
1147
|
|
|
$_SESSION['MIN_FIELD_INTEGER'] = $minFieldFloat; |
1148
|
|
|
$_SESSION['MAX_FIELD_INTEGER'] = $maxFieldFloat; |
1149
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Float value is out of range.'); |
1150
|
|
|
return ERROR_FLOAT_VALUE_OUT_OF_RANGE; |
1151
|
|
|
} |
1152
|
|
|
} |
1153
|
|
|
|
1154
|
|
|
break; |
1155
|
|
|
|
1156
|
|
|
case FIELD_TYPE_STRING: |
1157
|
|
|
case FIELD_TYPE_MULTILINED: |
1158
|
|
|
|
1159
|
|
|
$value = ustrcut($value, $row['param1']); |
1160
|
|
|
|
1161
|
|
|
// if regexp to check is set - check if value matches it |
1162
|
|
|
if (!is_null($row['regex_check']) && ustrlen($value) != 0) |
1163
|
|
|
{ |
1164
|
|
|
if (preg_match("/{$row['regex_check']}/", $value) == 0) |
1165
|
|
|
{ |
1166
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Field value fails regex check.'); |
1167
|
|
|
|
1168
|
|
|
$_SESSION['FIELD_NAME'] = $row['field_name']; |
1169
|
|
|
$_SESSION['FIELD_VALUE'] = $value; |
1170
|
|
|
|
1171
|
|
|
return ERROR_VALUE_FAILS_REGEX_CHECK; |
1172
|
|
|
} |
1173
|
|
|
} |
1174
|
|
|
|
1175
|
|
|
break; |
1176
|
|
|
|
1177
|
|
|
case FIELD_TYPE_CHECKBOX: |
1178
|
|
|
break; // nop |
1179
|
|
|
|
1180
|
|
|
case FIELD_TYPE_LIST: |
1181
|
|
|
|
1182
|
|
|
if (ustrlen($value) != 0) |
1183
|
|
|
{ |
1184
|
|
|
if (!is_intvalue($value)) |
1185
|
|
|
{ |
1186
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Invalid list value.'); |
1187
|
|
|
return ERROR_INVALID_INTEGER_VALUE; |
1188
|
|
|
} |
1189
|
|
|
|
1190
|
|
|
$intvalue = intval($value); |
1191
|
|
|
|
1192
|
|
|
if ($intvalue < 1 || |
1193
|
|
|
$intvalue > MAXINT) |
1194
|
|
|
{ |
1195
|
|
|
$_SESSION['FIELD_NAME'] = $row['field_name']; |
1196
|
|
|
$_SESSION['MIN_FIELD_INTEGER'] = 1; |
1197
|
|
|
$_SESSION['MAX_FIELD_INTEGER'] = MAXINT; |
1198
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] List value is out of range.'); |
1199
|
|
|
return ERROR_INTEGER_VALUE_OUT_OF_RANGE; |
1200
|
|
|
} |
1201
|
|
|
|
1202
|
|
|
$rsl = dal_query('values/lvfndk1.sql', $row['field_id'], $value); |
1203
|
|
|
|
1204
|
|
|
if ($rsl->rows == 0) |
1205
|
|
|
{ |
1206
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] List value not found.'); |
1207
|
|
|
return ERROR_INVALID_INTEGER_VALUE; |
1208
|
|
|
} |
1209
|
|
|
} |
1210
|
|
|
|
1211
|
|
|
break; |
1212
|
|
|
|
1213
|
|
|
case FIELD_TYPE_RECORD: |
1214
|
|
|
|
1215
|
|
|
if (ustrlen($value) != 0) |
1216
|
|
|
{ |
1217
|
|
|
if (!is_intvalue($value)) |
1218
|
|
|
{ |
1219
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Invalid record ID.'); |
1220
|
|
|
return ERROR_INVALID_INTEGER_VALUE; |
1221
|
|
|
} |
1222
|
|
|
|
1223
|
|
|
if (intval($value) == $record_id) |
1224
|
|
|
{ |
1225
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] The same record ID cannot be specified.'); |
1226
|
|
|
return ERROR_RECORD_NOT_FOUND; |
1227
|
|
|
} |
1228
|
|
|
|
1229
|
|
|
$record = record_find(intval($value)); |
1230
|
|
|
|
1231
|
|
|
if (!$record) |
1232
|
|
|
{ |
1233
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Record not found.'); |
1234
|
|
|
return ERROR_RECORD_NOT_FOUND; |
1235
|
|
|
} |
1236
|
|
|
} |
1237
|
|
|
|
1238
|
|
|
break; |
1239
|
|
|
|
1240
|
|
|
case FIELD_TYPE_DATE: |
1241
|
|
|
|
1242
|
|
|
if (ustrlen($value) != 0) |
1243
|
|
|
{ |
1244
|
|
|
$today = date_floor($operation == OPERATION_MODIFY_RECORD ? $row['event_time'] : time()); |
1245
|
|
|
|
1246
|
|
|
$row['param1'] = date_offset($today, $row['param1']); |
1247
|
|
|
$row['param2'] = date_offset($today, $row['param2']); |
1248
|
|
|
|
1249
|
|
|
$date = ustr2date($value); |
1250
|
|
|
|
1251
|
|
|
if ($date == -1) |
1252
|
|
|
{ |
1253
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Invalid date value.'); |
1254
|
|
|
return ERROR_INVALID_DATE_VALUE; |
1255
|
|
|
} |
1256
|
|
|
|
1257
|
|
|
$date += $_SESSION[VAR_TIMEZONE] - intval(date('Z')); |
1258
|
|
|
|
1259
|
|
|
if ($date < $row['param1'] || |
1260
|
|
|
$date > $row['param2']) |
1261
|
|
|
{ |
1262
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Date value is out of range.'); |
1263
|
|
|
|
1264
|
|
|
$_SESSION['FIELD_NAME'] = $row['field_name']; |
1265
|
|
|
$_SESSION['MIN_FIELD_INTEGER'] = get_date($row['param1']); |
1266
|
|
|
$_SESSION['MAX_FIELD_INTEGER'] = get_date($row['param2']); |
1267
|
|
|
|
1268
|
|
|
return ERROR_DATE_VALUE_OUT_OF_RANGE; |
1269
|
|
|
} |
1270
|
|
|
} |
1271
|
|
|
|
1272
|
|
|
break; |
1273
|
|
|
|
1274
|
|
|
case FIELD_TYPE_DURATION: |
1275
|
|
|
|
1276
|
|
View Code Duplication |
if (ustrlen($value) != 0) |
|
|
|
|
1277
|
|
|
{ |
1278
|
|
|
$duration = ustr2time($value); |
1279
|
|
|
|
1280
|
|
|
if ($duration == -1) |
1281
|
|
|
{ |
1282
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Invalid duration value.'); |
1283
|
|
|
return ERROR_INVALID_TIME_VALUE; |
1284
|
|
|
} |
1285
|
|
|
|
1286
|
|
|
if ($duration < $row['param1'] || |
1287
|
|
|
$duration > $row['param2']) |
1288
|
|
|
{ |
1289
|
|
|
$_SESSION['FIELD_NAME'] = $row['field_name']; |
1290
|
|
|
$_SESSION['MIN_FIELD_INTEGER'] = time2ustr($row['param1']); |
1291
|
|
|
$_SESSION['MAX_FIELD_INTEGER'] = time2ustr($row['param2']); |
1292
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_validate] Duration value is out of range.'); |
1293
|
|
|
return ERROR_TIME_VALUE_OUT_OF_RANGE; |
1294
|
|
|
} |
1295
|
|
|
} |
1296
|
|
|
|
1297
|
|
|
break; |
1298
|
|
|
|
1299
|
|
|
default: |
1300
|
|
|
debug_write_log(DEBUG_WARNING, '[record_validate] Unknown field type = ' . $row['field_type']); |
1301
|
|
|
} |
1302
|
|
|
} |
1303
|
|
|
|
1304
|
|
|
return NO_ERROR; |
1305
|
|
|
} |
1306
|
|
|
|
1307
|
|
|
/** |
1308
|
|
|
* Creates new record. |
1309
|
|
|
* |
1310
|
|
|
* @param int &$id ID of newly created record (used as output only). |
1311
|
|
|
* @param string $subject Subject of new record. |
1312
|
|
|
* @param int $state_id ID of initial state of new record. |
1313
|
|
|
* @param int $responsible_id If record should be assigned on creation, then ID of responsible of new record; NULL (default) otherwise. |
1314
|
|
|
* @param int $clone_id If record is being cloned from another, ID of original record, 0 (default) otherwise. |
1315
|
|
|
* @return int Error code: |
1316
|
|
|
* <ul> |
1317
|
|
|
* <li>{@link NO_ERROR} - record is successfully created</li> |
1318
|
|
|
* <li>{@link ERROR_NOT_FOUND} - failure on attempt to create new record</li> |
1319
|
|
|
* </ul> |
1320
|
|
|
*/ |
1321
|
|
|
function record_create (&$id, $subject, $state_id, $responsible_id = NULL, $clone_id = 0) |
1322
|
|
|
{ |
1323
|
|
|
debug_write_log(DEBUG_TRACE, '[record_create]'); |
1324
|
|
|
debug_write_log(DEBUG_DUMP, '[record_create] $subject = ' . $subject); |
1325
|
|
|
debug_write_log(DEBUG_DUMP, '[record_create] $state_id = ' . $state_id); |
1326
|
|
|
debug_write_log(DEBUG_DUMP, '[record_create] $responsible_id = ' . $responsible_id); |
1327
|
|
|
|
1328
|
|
|
$time = time(); |
1329
|
|
|
|
1330
|
|
|
// Create a record. |
1331
|
|
|
dal_query('records/create.sql', |
1332
|
|
|
$state_id, |
1333
|
|
|
$subject, |
1334
|
|
|
is_null($responsible_id) ? NULL : $responsible_id, |
1335
|
|
|
$_SESSION[VAR_USERID], |
1336
|
|
|
$time); |
1337
|
|
|
|
1338
|
|
|
// Find newly created record. |
1339
|
|
|
$rs = dal_query('records/fndk.sql', |
1340
|
|
|
$_SESSION[VAR_USERID], |
1341
|
|
|
$time); |
1342
|
|
|
|
1343
|
|
|
if ($rs->rows == 0) |
1344
|
|
|
{ |
1345
|
|
|
debug_write_log(DEBUG_ERROR, '[record_create] Record cannot be found.'); |
1346
|
|
|
return ERROR_NOT_FOUND; |
1347
|
|
|
} |
1348
|
|
|
|
1349
|
|
|
$id = $rs->fetch('record_id'); |
1350
|
|
|
|
1351
|
|
|
if ($clone_id != 0) |
1352
|
|
|
{ |
1353
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_create] Record is being cloned.'); |
1354
|
|
|
event_create($id, EVENT_RECORD_CLONED, $time - 1, $clone_id); |
1355
|
|
|
} |
1356
|
|
|
|
1357
|
|
|
$event = event_create($id, EVENT_RECORD_CREATED, $time, $state_id); |
1358
|
|
|
|
1359
|
|
|
if (!is_null($responsible_id)) |
1360
|
|
|
{ |
1361
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_create] Responsible is being set.'); |
1362
|
|
|
$event2 = event_create($id, EVENT_RECORD_ASSIGNED, time(), $responsible_id); |
1363
|
|
|
} |
1364
|
|
|
|
1365
|
|
|
// Create current values of all custom fields of new record. |
1366
|
|
|
$rs = dal_query('fields/list.sql', $state_id, 'field_order'); |
1367
|
|
|
|
1368
|
|
|
while (($row = $rs->fetch())) |
1369
|
|
|
{ |
1370
|
|
|
$name = 'field' . $row['field_id']; |
1371
|
|
|
$value = ($row['field_type'] == FIELD_TYPE_CHECKBOX ? isset($_REQUEST[$name]) : trim(try_request($name))); |
1372
|
|
|
|
1373
|
|
View Code Duplication |
switch ($row['field_type']) |
|
|
|
|
1374
|
|
|
{ |
1375
|
|
|
case FIELD_TYPE_NUMBER: |
1376
|
|
|
case FIELD_TYPE_LIST: |
1377
|
|
|
case FIELD_TYPE_RECORD: |
1378
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : intval($value))); |
1379
|
|
|
break; |
1380
|
|
|
case FIELD_TYPE_FLOAT: |
1381
|
|
|
value_create_float($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustrcut($value, ustrlen(MAX_FIELD_FLOAT)))); |
1382
|
|
|
break; |
1383
|
|
|
case FIELD_TYPE_STRING: |
1384
|
|
|
value_create_string($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustrcut($value, $row['param1']))); |
1385
|
|
|
break; |
1386
|
|
|
case FIELD_TYPE_MULTILINED: |
1387
|
|
|
value_create_multilined($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustrcut($value, $row['param1']))); |
1388
|
|
|
break; |
1389
|
|
|
case FIELD_TYPE_CHECKBOX: |
1390
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], bool2sql((bool)(ustrlen($value) == 0 ? 0 : intval($value)))); |
1391
|
|
|
break; |
1392
|
|
|
case FIELD_TYPE_DATE: |
1393
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustr2date($value))); |
1394
|
|
|
break; |
1395
|
|
|
case FIELD_TYPE_DURATION: |
1396
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustr2time($value))); |
1397
|
|
|
break; |
1398
|
|
|
default: |
1399
|
|
|
debug_write_log(DEBUG_WARNING, '[record_create] Unknown field type = ' . $row['field_type']); |
1400
|
|
|
} |
1401
|
|
|
} |
1402
|
|
|
|
1403
|
|
|
event_mail($event); |
1404
|
|
|
|
1405
|
|
|
if (!is_null($responsible_id)) |
1406
|
|
|
{ |
1407
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_create] Responsible is set.'); |
1408
|
|
|
event_mail($event2); |
1409
|
|
|
} |
1410
|
|
|
|
1411
|
|
|
return NO_ERROR; |
1412
|
|
|
} |
1413
|
|
|
|
1414
|
|
|
/** |
1415
|
|
|
* Modifies specified record. |
1416
|
|
|
* |
1417
|
|
|
* @param int $id ID of record to be modified. |
1418
|
|
|
* @param string $subject New subject of the record. |
1419
|
|
|
* @param int $creator_id Current author of record. |
1420
|
|
|
* @param int $responsible_id Current responsible of record (NULL, if record is not assigned). |
1421
|
|
|
* @return int Error code: |
1422
|
|
|
* <ul> |
1423
|
|
|
* <li>{@link NO_ERROR} - record is successfully modified</li> |
1424
|
|
|
* <li>{@link ERROR_NOT_FOUND} - record cannot be found</li> |
1425
|
|
|
* </ul> |
1426
|
|
|
*/ |
1427
|
|
|
function record_modify ($id, $subject, $creator_id, $responsible_id) |
1428
|
|
|
{ |
1429
|
|
|
debug_write_log(DEBUG_TRACE, '[record_modify]'); |
1430
|
|
|
debug_write_log(DEBUG_DUMP, '[record_modify] $id = ' . $id); |
1431
|
|
|
debug_write_log(DEBUG_DUMP, '[record_modify] $subject = ' . $subject); |
1432
|
|
|
debug_write_log(DEBUG_DUMP, '[record_modify] $creator_id = ' . $creator_id); |
1433
|
|
|
debug_write_log(DEBUG_DUMP, '[record_modify] $responsible_id = ' . $responsible_id); |
1434
|
|
|
|
1435
|
|
|
$rs = dal_query('records/fndsubj.sql', $id); |
1436
|
|
|
|
1437
|
|
|
if ($rs->rows == 0) |
1438
|
|
|
{ |
1439
|
|
|
debug_write_log(DEBUG_ERROR, '[record_modify] Record cannot be found.'); |
1440
|
|
|
return ERROR_NOT_FOUND; |
1441
|
|
|
} |
1442
|
|
|
|
1443
|
|
|
$event = event_create($id, EVENT_RECORD_MODIFIED, time()); |
1444
|
|
|
|
1445
|
|
|
$row = $rs->fetch(); |
1446
|
|
|
|
1447
|
|
|
if ($row['subject'] != $subject) |
1448
|
|
|
{ |
1449
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_modify] Subject is being changed.'); |
1450
|
|
|
|
1451
|
|
|
$old_value_id = value_find_string($row['subject']); |
1452
|
|
|
$new_value_id = value_find_string($subject); |
1453
|
|
|
|
1454
|
|
|
dal_query('changes/create.sql', |
1455
|
|
|
$event['event_id'], |
1456
|
|
|
NULL, |
1457
|
|
|
is_null($old_value_id) ? NULL : $old_value_id, |
1458
|
|
|
is_null($new_value_id) ? NULL : $new_value_id); |
1459
|
|
|
|
1460
|
|
|
dal_query('records/modify.sql', |
1461
|
|
|
$id, |
1462
|
|
|
$subject); |
1463
|
|
|
} |
1464
|
|
|
|
1465
|
|
|
$rs = dal_query('records/elist.sql', $id); |
1466
|
|
|
|
1467
|
|
|
while (($row = $rs->fetch())) |
1468
|
|
|
{ |
1469
|
|
|
$rsf = dal_query('records/flist.sql', |
1470
|
|
|
$id, |
1471
|
|
|
$row['state_id'], |
1472
|
|
|
$creator_id, |
1473
|
|
|
is_null($responsible_id) ? 0 : $responsible_id, |
1474
|
|
|
$_SESSION[VAR_USERID], |
1475
|
|
|
FIELD_ALLOW_TO_WRITE); |
1476
|
|
|
|
1477
|
|
|
while (($row = $rsf->fetch())) |
1478
|
|
|
{ |
1479
|
|
|
$name = 'field' . $row['field_id']; |
1480
|
|
|
$value = ($row['field_type'] == FIELD_TYPE_CHECKBOX ? isset($_REQUEST[$name]) : trim(try_request($name))); |
1481
|
|
|
|
1482
|
|
|
switch ($row['field_type']) |
1483
|
|
|
{ |
1484
|
|
|
case FIELD_TYPE_NUMBER: |
1485
|
|
|
case FIELD_TYPE_LIST: |
1486
|
|
|
case FIELD_TYPE_RECORD: |
1487
|
|
|
value_modify_number($id, $event['event_id'], $row['field_id'], (ustrlen($value) == 0 ? NULL : intval($value))); |
1488
|
|
|
break; |
1489
|
|
|
case FIELD_TYPE_FLOAT: |
1490
|
|
|
value_modify_float($id, $event['event_id'], $row['field_id'], (ustrlen($value) == 0 ? NULL : ustrcut($value, ustrlen(MAX_FIELD_FLOAT)))); |
1491
|
|
|
break; |
1492
|
|
|
case FIELD_TYPE_STRING: |
1493
|
|
|
value_modify_string($id, $event['event_id'], $row['field_id'], (ustrlen($value) == 0 ? NULL : ustrcut($value, $row['param1']))); |
1494
|
|
|
break; |
1495
|
|
|
case FIELD_TYPE_MULTILINED: |
1496
|
|
|
value_modify_multilined($id, $event['event_id'], $row['field_id'], (ustrlen($value) == 0 ? NULL : ustrcut($value, $row['param1']))); |
1497
|
|
|
break; |
1498
|
|
|
case FIELD_TYPE_CHECKBOX: |
1499
|
|
|
value_modify_number($id, $event['event_id'], $row['field_id'], bool2sql((bool)(ustrlen($value) == 0 ? 0 : intval($value)))); |
1500
|
|
|
break; |
1501
|
|
|
case FIELD_TYPE_DATE: |
1502
|
|
|
value_modify_number($id, $event['event_id'], $row['field_id'], (ustrlen($value) == 0 ? NULL : ustr2date($value))); |
1503
|
|
|
break; |
1504
|
|
|
case FIELD_TYPE_DURATION: |
1505
|
|
|
value_modify_number($id, $event['event_id'], $row['field_id'], (ustrlen($value) == 0 ? NULL : ustr2time($value))); |
1506
|
|
|
break; |
1507
|
|
|
default: |
1508
|
|
|
debug_write_log(DEBUG_WARNING, '[record_modify] Unknown field type = ' . $row['field_type']); |
1509
|
|
|
} |
1510
|
|
|
} |
1511
|
|
|
} |
1512
|
|
|
|
1513
|
|
|
$rs = dal_query('changes/count.sql', $event['event_id']); |
1514
|
|
|
|
1515
|
|
|
if ($rs->fetch(0) == 0) |
1516
|
|
|
{ |
1517
|
|
|
event_destroy($event['event_id']); |
1518
|
|
|
} |
1519
|
|
|
else |
1520
|
|
|
{ |
1521
|
|
|
event_mail($event); |
1522
|
|
|
} |
1523
|
|
|
|
1524
|
|
|
return NO_ERROR; |
1525
|
|
|
} |
1526
|
|
|
|
1527
|
|
|
/** |
1528
|
|
|
* Deletes specified record. |
1529
|
|
|
* |
1530
|
|
|
* @param int $id ID of record to be deleted. |
1531
|
|
|
* @return int Always {@link NO_ERROR}. |
1532
|
|
|
*/ |
1533
|
|
|
function record_delete ($id) |
1534
|
|
|
{ |
1535
|
|
|
debug_write_log(DEBUG_TRACE, '[record_delete]'); |
1536
|
|
|
debug_write_log(DEBUG_DUMP, '[record_delete] $id = ' . $id); |
1537
|
|
|
|
1538
|
|
|
$rs = dal_query('attachs/list.sql', $id, 'attachment_id'); |
1539
|
|
|
|
1540
|
|
|
while (($row = $rs->fetch())) |
1541
|
|
|
{ |
1542
|
|
|
@unlink(ATTACHMENTS_PATH . $row['attachment_id']); |
1543
|
|
|
} |
1544
|
|
|
|
1545
|
|
|
dal_query('comments/delall.sql', $id); |
1546
|
|
|
dal_query('attachs/delall.sql', $id); |
1547
|
|
|
dal_query('changes/delall.sql', $id); |
1548
|
|
|
dal_query('values/delall.sql', $id); |
1549
|
|
|
dal_query('events/delall.sql', $id); |
1550
|
|
|
dal_query('depends/delall.sql', $id); |
1551
|
|
|
dal_query('records/unreadall2.sql', $id); |
1552
|
|
|
dal_query('records/unsubscribe3.sql', $id); |
1553
|
|
|
dal_query('records/delete.sql', $id); |
1554
|
|
|
|
1555
|
|
|
return NO_ERROR; |
1556
|
|
|
} |
1557
|
|
|
|
1558
|
|
|
/** |
1559
|
|
|
* Postpones specified record. |
1560
|
|
|
* |
1561
|
|
|
* @param int $id ID of record to be postponed. |
1562
|
|
|
* @param int $date Unix timestamp of the date when record will be resumed automatically. |
1563
|
|
|
* @return int Always {@link NO_ERROR}. |
1564
|
|
|
*/ |
1565
|
|
|
function record_postpone ($id, $date) |
1566
|
|
|
{ |
1567
|
|
|
debug_write_log(DEBUG_TRACE, '[record_postpone]'); |
1568
|
|
|
debug_write_log(DEBUG_DUMP, '[record_postpone] $id = ' . $id); |
1569
|
|
|
debug_write_log(DEBUG_DUMP, '[record_postpone] $date = ' . $date); |
1570
|
|
|
|
1571
|
|
|
dal_query('records/postpone.sql', $id, $date); |
1572
|
|
|
|
1573
|
|
|
return NO_ERROR; |
1574
|
|
|
} |
1575
|
|
|
|
1576
|
|
|
/** |
1577
|
|
|
* Resumes specified postponed record. |
1578
|
|
|
* |
1579
|
|
|
* @param int $id ID of record to be resumed. |
1580
|
|
|
* @return int Always {@link NO_ERROR}. |
1581
|
|
|
*/ |
1582
|
|
|
function record_resume ($id) |
1583
|
|
|
{ |
1584
|
|
|
debug_write_log(DEBUG_TRACE, '[record_resume]'); |
1585
|
|
|
debug_write_log(DEBUG_DUMP, '[record_resume] $id = ' . $id); |
1586
|
|
|
|
1587
|
|
|
dal_query('records/postpone.sql', $id, 0); |
1588
|
|
|
|
1589
|
|
|
return NO_ERROR; |
1590
|
|
|
} |
1591
|
|
|
|
1592
|
|
|
/** |
1593
|
|
|
* Assigns specified record. |
1594
|
|
|
* |
1595
|
|
|
* @param int $rid ID of record to be assigned. |
1596
|
|
|
* @param int $aid ID of new responsible. |
1597
|
|
|
* @return int Always {@link NO_ERROR}. |
1598
|
|
|
*/ |
1599
|
|
|
function record_assign ($rid, $aid) |
1600
|
|
|
{ |
1601
|
|
|
debug_write_log(DEBUG_TRACE, '[record_assign]'); |
1602
|
|
|
debug_write_log(DEBUG_DUMP, '[record_assign] $rid = ' . $rid); |
1603
|
|
|
debug_write_log(DEBUG_DUMP, '[record_assign] $aid = ' . $aid); |
1604
|
|
|
|
1605
|
|
|
dal_query('records/assign.sql', $rid, $aid); |
1606
|
|
|
|
1607
|
|
|
return NO_ERROR; |
1608
|
|
|
} |
1609
|
|
|
|
1610
|
|
|
/** |
1611
|
|
|
* Marks specified record as read (for current user). |
1612
|
|
|
* |
1613
|
|
|
* @param int $id ID of record to be marked as read. |
1614
|
|
|
* @return int Always {@link NO_ERROR}. |
1615
|
|
|
*/ |
1616
|
|
|
function record_read ($id) |
1617
|
|
|
{ |
1618
|
|
|
debug_write_log(DEBUG_TRACE, '[record_read]'); |
1619
|
|
|
debug_write_log(DEBUG_DUMP, '[record_read] $id = ' . $id); |
1620
|
|
|
|
1621
|
|
|
if (get_user_level() != USER_LEVEL_GUEST) |
1622
|
|
|
{ |
1623
|
|
|
dal_query('records/unread.sql', $id, $_SESSION[VAR_USERID]); |
1624
|
|
|
dal_query('records/read.sql', $id, $_SESSION[VAR_USERID], time()); |
1625
|
|
|
} |
1626
|
|
|
|
1627
|
|
|
return NO_ERROR; |
1628
|
|
|
} |
1629
|
|
|
|
1630
|
|
|
/** |
1631
|
|
|
* Marks specified record as unread (for current user). |
1632
|
|
|
* |
1633
|
|
|
* @param int $id ID of record to be marked as unread. |
1634
|
|
|
* @return int Always {@link NO_ERROR}. |
1635
|
|
|
*/ |
1636
|
|
View Code Duplication |
function record_unread ($id) |
|
|
|
|
1637
|
|
|
{ |
1638
|
|
|
debug_write_log(DEBUG_TRACE, '[record_unread]'); |
1639
|
|
|
debug_write_log(DEBUG_DUMP, '[record_unread] $id = ' . $id); |
1640
|
|
|
|
1641
|
|
|
if (get_user_level() != USER_LEVEL_GUEST) |
1642
|
|
|
{ |
1643
|
|
|
dal_query('records/unread.sql', $id, $_SESSION[VAR_USERID]); |
1644
|
|
|
} |
1645
|
|
|
|
1646
|
|
|
return NO_ERROR; |
1647
|
|
|
} |
1648
|
|
|
|
1649
|
|
|
/** |
1650
|
|
|
* Change state of specified record. |
1651
|
|
|
* |
1652
|
|
|
* @param int $id ID of record which state should be changed. |
1653
|
|
|
* @param int $state_id New state of the record. |
1654
|
|
|
* @param int $responsible_id ID of new responsible: |
1655
|
|
|
* <ul> |
1656
|
|
|
* <li>account ID, if the record should be assigned</li> |
1657
|
|
|
* <li>NULL, if the current assignment should be removed</li> |
1658
|
|
|
* <li>0, if current assignment should be remained as is</li> |
1659
|
|
|
* </ul> |
1660
|
|
|
* @param bool $close TRUE if new state is final; FALSE otherwise. |
1661
|
|
|
* @param bool $reopen TRUE if the record is closed and being reopened; FALSE otherwise. |
1662
|
|
|
* @return int Always {@link NO_ERROR}. |
1663
|
|
|
*/ |
1664
|
|
|
function state_change ($id, $state_id, $responsible_id, $close = FALSE, $reopen = FALSE) |
1665
|
|
|
{ |
1666
|
|
|
debug_write_log(DEBUG_TRACE, '[state_change]'); |
1667
|
|
|
debug_write_log(DEBUG_DUMP, '[state_change] $id = ' . $id); |
1668
|
|
|
debug_write_log(DEBUG_DUMP, '[state_change] $state_id = ' . $state_id); |
1669
|
|
|
debug_write_log(DEBUG_DUMP, '[state_change] $responsible_id = ' . $responsible_id); |
1670
|
|
|
debug_write_log(DEBUG_DUMP, '[state_change] $close = ' . $close); |
1671
|
|
|
debug_write_log(DEBUG_DUMP, '[state_change] $reopen = ' . $reopen); |
1672
|
|
|
|
1673
|
|
|
dal_query('records/state.sql', |
1674
|
|
|
$id, |
1675
|
|
|
$state_id); |
1676
|
|
|
|
1677
|
|
|
$event = event_create($id, |
1678
|
|
|
$reopen ? EVENT_RECORD_REOPENED : EVENT_RECORD_STATE_CHANGED, |
1679
|
|
|
time(), |
1680
|
|
|
$state_id); |
1681
|
|
|
|
1682
|
|
|
$rs = dal_query('fields/list.sql', $state_id, 'field_order'); |
1683
|
|
|
|
1684
|
|
|
while (($row = $rs->fetch())) |
1685
|
|
|
{ |
1686
|
|
|
$name = 'field' . $row['field_id']; |
1687
|
|
|
$value = ($row['field_type'] == FIELD_TYPE_CHECKBOX ? isset($_REQUEST[$name]) : trim(try_request($name))); |
1688
|
|
|
|
1689
|
|
|
dal_query('values/latest.sql', $id, $row['field_id']); |
1690
|
|
|
|
1691
|
|
View Code Duplication |
switch ($row['field_type']) |
|
|
|
|
1692
|
|
|
{ |
1693
|
|
|
case FIELD_TYPE_NUMBER: |
1694
|
|
|
case FIELD_TYPE_LIST: |
1695
|
|
|
case FIELD_TYPE_RECORD: |
1696
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : intval($value))); |
1697
|
|
|
break; |
1698
|
|
|
case FIELD_TYPE_FLOAT: |
1699
|
|
|
value_create_float($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustrcut($value, ustrlen(MAX_FIELD_FLOAT)))); |
1700
|
|
|
break; |
1701
|
|
|
case FIELD_TYPE_STRING: |
1702
|
|
|
value_create_string($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustrcut($value, $row['param1']))); |
1703
|
|
|
break; |
1704
|
|
|
case FIELD_TYPE_MULTILINED: |
1705
|
|
|
value_create_multilined($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustrcut($value, $row['param1']))); |
1706
|
|
|
break; |
1707
|
|
|
case FIELD_TYPE_CHECKBOX: |
1708
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], bool2sql((bool)(ustrlen($value) == 0 ? 0 : intval($value)))); |
1709
|
|
|
break; |
1710
|
|
|
case FIELD_TYPE_DATE: |
1711
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustr2date($value))); |
1712
|
|
|
break; |
1713
|
|
|
case FIELD_TYPE_DURATION: |
1714
|
|
|
value_create_number($event['event_id'], $row['field_id'], $row['field_type'], (ustrlen($value) == 0 ? NULL : ustr2time($value))); |
1715
|
|
|
break; |
1716
|
|
|
default: |
1717
|
|
|
debug_write_log(DEBUG_WARNING, '[state_change] Unknown field type = ' . $row['field_type']); |
1718
|
|
|
} |
1719
|
|
|
} |
1720
|
|
|
|
1721
|
|
|
event_mail($event); |
1722
|
|
|
|
1723
|
|
|
if ($close) |
1724
|
|
|
{ |
1725
|
|
|
debug_write_log(DEBUG_NOTICE, '[state_change] Close record.'); |
1726
|
|
|
dal_query('records/close.sql', $id, time()); |
1727
|
|
|
} |
1728
|
|
|
else |
1729
|
|
|
{ |
1730
|
|
|
if ($reopen) |
1731
|
|
|
{ |
1732
|
|
|
debug_write_log(DEBUG_NOTICE, '[state_change] Reopen record.'); |
1733
|
|
|
dal_query('records/open.sql', $id); |
1734
|
|
|
} |
1735
|
|
|
|
1736
|
|
|
if (is_null($responsible_id)) |
1737
|
|
|
{ |
1738
|
|
|
debug_write_log(DEBUG_NOTICE, '[state_change] Remove responsible.'); |
1739
|
|
|
dal_query('records/assign.sql', $id, NULL); |
1740
|
|
|
} |
1741
|
|
|
elseif ($responsible_id != 0) |
1742
|
|
|
{ |
1743
|
|
|
debug_write_log(DEBUG_NOTICE, '[state_change] Assign responsible.'); |
1744
|
|
|
dal_query('records/assign.sql', $id, $responsible_id); |
1745
|
|
|
$event = event_create($id, EVENT_RECORD_ASSIGNED, time(), $responsible_id); |
1746
|
|
|
event_mail($event); |
1747
|
|
|
} |
1748
|
|
|
} |
1749
|
|
|
|
1750
|
|
|
return NO_ERROR; |
1751
|
|
|
} |
1752
|
|
|
|
1753
|
|
|
/** |
1754
|
|
|
* Returns {@link CRecordset DAL recordset} which contains all events of specified record, |
1755
|
|
|
* sorted in accordance with current sort mode. |
1756
|
|
|
* |
1757
|
|
|
* @param int $id Record ID. |
1758
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
1759
|
|
|
* @param int &$sort Sort mode (used as output only). The function retrieves current sort mode from |
1760
|
|
|
* client cookie ({@link COOKIE_EVENTS_SORT}) and updates it, if it's out of valid range. |
1761
|
|
|
* @param int &$page Number of current page tab (used as output only). The function retrieves current |
1762
|
|
|
* page from client cookie ({@link COOKIE_EVENTS_PAGE}) and updates it, if it's out of valid range. |
1763
|
|
|
* @return CRecordset Recordset with list of events. |
1764
|
|
|
*/ |
1765
|
|
|
function history_list ($id, $permissions, &$sort, &$page) |
1766
|
|
|
{ |
1767
|
|
|
debug_write_log(DEBUG_TRACE, '[history_list]'); |
1768
|
|
|
debug_write_log(DEBUG_DUMP, '[history_list] $id = ' . $id); |
1769
|
|
|
debug_write_log(DEBUG_DUMP, '[history_list] $permissions = ' . $permissions); |
1770
|
|
|
|
1771
|
|
|
$sort_modes = array |
1772
|
|
|
( |
1773
|
|
|
1 => 'event_time asc, event_type asc', |
1774
|
|
|
2 => 'fullname asc, username asc, event_time asc, event_type asc', |
1775
|
|
|
3 => 'event_type asc, event_time asc', |
1776
|
|
|
4 => 'event_time desc, event_type desc', |
1777
|
|
|
5 => 'fullname desc, username desc, event_time desc, event_type desc', |
1778
|
|
|
6 => 'event_type desc, event_time desc', |
1779
|
|
|
); |
1780
|
|
|
|
1781
|
|
|
$sort = try_request('sort', try_cookie(COOKIE_EVENTS_SORT)); |
1782
|
|
|
$sort = ustr2int($sort, 1, count($sort_modes)); |
1783
|
|
|
|
1784
|
|
|
$page = try_request('page', try_cookie(COOKIE_EVENTS_PAGE)); |
1785
|
|
|
$page = ustr2int($page, 1, MAXINT); |
1786
|
|
|
|
1787
|
|
|
save_cookie(COOKIE_EVENTS_SORT, $sort); |
1788
|
|
|
save_cookie(COOKIE_EVENTS_PAGE, $page); |
1789
|
|
|
|
1790
|
|
|
return dal_query('events/list.sql', $id, ($permissions & PERMIT_CONFIDENTIAL_COMMENTS) ? EVENT_UNUSED : EVENT_CONFIDENTIAL_COMMENT, $sort_modes[$sort]); |
1791
|
|
|
} |
1792
|
|
|
|
1793
|
|
|
/** |
1794
|
|
|
* Returns {@link CRecordset DAL recordset} which contains all changes of specified record, |
1795
|
|
|
* sorted in accordance with current sort mode. |
1796
|
|
|
* |
1797
|
|
|
* @param int $id Record ID. |
1798
|
|
|
* @param int $creator_id Current author of the record. |
1799
|
|
|
* @param int $responsible_id Current responsible of the record (NULL, if record is not assigned). |
1800
|
|
|
* @param int &$sort Sort mode (used as output only). The function retrieves current sort mode from |
1801
|
|
|
* client cookie ({@link COOKIE_CHANGES_SORT}) and updates it, if it's out of valid range. |
1802
|
|
|
* @param int &$page Number of current page tab (used as output only). The function retrieves current |
1803
|
|
|
* page from client cookie ({@link COOKIE_CHANGES_PAGE}) and updates it, if it's out of valid range. |
1804
|
|
|
* @return CRecordset Recordset with list of changes. |
1805
|
|
|
*/ |
1806
|
|
|
function changes_list ($id, $creator_id, $responsible_id, &$sort, &$page) |
1807
|
|
|
{ |
1808
|
|
|
debug_write_log(DEBUG_TRACE, '[changes_list]'); |
1809
|
|
|
debug_write_log(DEBUG_DUMP, '[changes_list] $id = ' . $id); |
1810
|
|
|
debug_write_log(DEBUG_DUMP, '[changes_list] $creator_id = ' . $creator_id); |
1811
|
|
|
debug_write_log(DEBUG_DUMP, '[changes_list] $responsible_id = ' . $responsible_id); |
1812
|
|
|
|
1813
|
|
|
$sort_modes = array |
1814
|
|
|
( |
1815
|
|
|
1 => 'event_time asc, field_order asc', |
1816
|
|
|
2 => 'fullname asc, username asc, event_time asc, field_order asc', |
1817
|
|
|
3 => 'field_name asc, event_time asc', |
1818
|
|
|
4 => '', |
1819
|
|
|
5 => '', |
1820
|
|
|
6 => 'event_time desc, field_order desc', |
1821
|
|
|
7 => 'fullname desc, username desc, event_time desc, field_order desc', |
1822
|
|
|
8 => 'field_name desc, event_time desc', |
1823
|
|
|
9 => '', |
1824
|
|
|
10 => '', |
1825
|
|
|
); |
1826
|
|
|
|
1827
|
|
|
$sort = try_request('sort', try_cookie(COOKIE_CHANGES_SORT)); |
1828
|
|
|
$sort = ustr2int($sort, 1, count($sort_modes)); |
1829
|
|
|
|
1830
|
|
|
$page = try_request('page', try_cookie(COOKIE_CHANGES_PAGE)); |
1831
|
|
|
$page = ustr2int($page, 1, MAXINT); |
1832
|
|
|
|
1833
|
|
|
save_cookie(COOKIE_CHANGES_SORT, $sort); |
1834
|
|
|
save_cookie(COOKIE_CHANGES_PAGE, $page); |
1835
|
|
|
|
1836
|
|
|
return dal_query('changes/list.sql', |
1837
|
|
|
$id, |
1838
|
|
|
$creator_id, |
1839
|
|
|
is_null($responsible_id) ? 0 : $responsible_id, |
1840
|
|
|
$_SESSION[VAR_USERID], |
1841
|
|
|
$sort_modes[$sort]); |
1842
|
|
|
} |
1843
|
|
|
|
1844
|
|
|
/** |
1845
|
|
|
* Finds in database and returns the information about specified comment. |
1846
|
|
|
* |
1847
|
|
|
* @param int $event_id ID of event, registered when comment has been added. |
1848
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
1849
|
|
|
* @return array Array with data if comment is found in database, FALSE otherwise. |
1850
|
|
|
*/ |
1851
|
|
|
function comment_find ($event_id, $permissions) |
1852
|
|
|
{ |
1853
|
|
|
debug_write_log(DEBUG_TRACE, '[comment_find]'); |
1854
|
|
|
debug_write_log(DEBUG_DUMP, '[comment_find] $event_id = ' . $event_id); |
1855
|
|
|
debug_write_log(DEBUG_DUMP, '[comment_find] $permissions = ' . $permissions); |
1856
|
|
|
|
1857
|
|
|
$rs = dal_query('comments/fndk.sql', $event_id); |
1858
|
|
|
$row = $rs->fetch(); |
1859
|
|
|
|
1860
|
|
|
return ($rs->rows == 0 ? FALSE : ($row['is_confidential'] && ($permissions & PERMIT_CONFIDENTIAL_COMMENTS) == 0 ? FALSE : $row)); |
1861
|
|
|
} |
1862
|
|
|
|
1863
|
|
|
/** |
1864
|
|
|
* Adds new comment to specified record. |
1865
|
|
|
* |
1866
|
|
|
* @param int $id Record ID. |
1867
|
|
|
* @param string $comment Text of comment. |
1868
|
|
|
* @param bool $is_confidential Whether the comment is confidential. |
1869
|
|
|
* @return int Error code: |
1870
|
|
|
* <ul> |
1871
|
|
|
* <li>{@link NO_ERROR} - template is successfully created</li> |
1872
|
|
|
* <li>{@link ERROR_INCOMPLETE_FORM} - at least one of required field is empty</li> |
1873
|
|
|
* <li>{@link ERROR_NOT_FOUND} - record cannot be found</li> |
1874
|
|
|
* </ul> |
1875
|
|
|
*/ |
1876
|
|
|
function comment_add ($id, $comment, $is_confidential = FALSE) |
1877
|
|
|
{ |
1878
|
|
|
debug_write_log(DEBUG_TRACE, '[comment_add]'); |
1879
|
|
|
debug_write_log(DEBUG_DUMP, '[comment_add] $id = ' . $id); |
1880
|
|
|
debug_write_log(DEBUG_DUMP, '[comment_add] $comment = ' . $comment); |
1881
|
|
|
debug_write_log(DEBUG_DUMP, '[comment_add] $is_confidential = ' . $is_confidential); |
1882
|
|
|
|
1883
|
|
|
if (ustrlen($comment) == 0) |
1884
|
|
|
{ |
1885
|
|
|
debug_write_log(DEBUG_NOTICE, '[comment_add] At least one required field is empty.'); |
1886
|
|
|
return ERROR_INCOMPLETE_FORM; |
1887
|
|
|
} |
1888
|
|
|
|
1889
|
|
|
$record = record_find($id); |
1890
|
|
|
|
1891
|
|
|
if (!$record) |
1892
|
|
|
{ |
1893
|
|
|
debug_write_log(DEBUG_ERROR, '[comment_add] Record cannot be found.'); |
1894
|
|
|
return ERROR_NOT_FOUND; |
1895
|
|
|
} |
1896
|
|
|
|
1897
|
|
|
$event = event_create($id, ($is_confidential ? EVENT_CONFIDENTIAL_COMMENT : EVENT_COMMENT_ADDED), time()); |
1898
|
|
|
|
1899
|
|
|
if (!$event) |
1900
|
|
|
{ |
1901
|
|
|
debug_write_log(DEBUG_ERROR, '[comment_add] Event cannot be found.'); |
1902
|
|
|
return ERROR_NOT_FOUND; |
1903
|
|
|
} |
1904
|
|
|
|
1905
|
|
|
if (DATABASE_DRIVER == DRIVER_ORACLE9) |
1906
|
|
|
{ |
1907
|
|
|
$handle = CDatabase::connect()->link->handle; |
1908
|
|
|
$sql = file_get_contents(LOCALROOT . '/sql/comments/oracle/create.sql'); |
1909
|
|
|
|
1910
|
|
|
$stid = ociparse($handle, $sql); |
1911
|
|
|
$clob = ocinewdescriptor($handle, OCI_D_LOB); |
1912
|
|
|
|
1913
|
|
|
ocibindbyname($stid, ":event_id", $event['event_id']); |
1914
|
|
|
ocibindbyname($stid, ":comment_body", $clob, -1, OCI_B_CLOB); |
1915
|
|
|
ocibindbyname($stid, ":is_confidential", bool2sql($is_confidential)); |
1916
|
|
|
|
1917
|
|
|
ociexecute($stid, OCI_DEFAULT); |
1918
|
|
|
$clob->save($comment); |
1919
|
|
|
ocicommit($handle); |
1920
|
|
|
} |
1921
|
|
|
else |
1922
|
|
|
{ |
1923
|
|
|
dal_query('comments/create.sql', |
1924
|
|
|
$comment, |
1925
|
|
|
$event['event_id'], |
1926
|
|
|
bool2sql($is_confidential)); |
1927
|
|
|
} |
1928
|
|
|
|
1929
|
|
|
event_mail($event); |
1930
|
|
|
|
1931
|
|
|
return NO_ERROR; |
1932
|
|
|
} |
1933
|
|
|
|
1934
|
|
|
/** |
1935
|
|
|
* Finds in database and returns the information about specified attachment. |
1936
|
|
|
* |
1937
|
|
|
* @param int $attachment_id Attachment ID. |
1938
|
|
|
* @return array Array with data if attachment is found in database, FALSE otherwise. |
1939
|
|
|
*/ |
1940
|
|
|
function attachment_find ($attachment_id) |
1941
|
|
|
{ |
1942
|
|
|
debug_write_log(DEBUG_TRACE, '[attachment_find]'); |
1943
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_find] $attachment_id = ' . $attachment_id); |
1944
|
|
|
|
1945
|
|
|
$rs = dal_query('attachs/fndid.sql', $attachment_id); |
1946
|
|
|
|
1947
|
|
|
return ($rs->rows == 0 ? FALSE : $rs->fetch()); |
1948
|
|
|
} |
1949
|
|
|
|
1950
|
|
|
/** |
1951
|
|
|
* Returns {@link CRecordset DAL recordset} which contains all attachments of specified record, |
1952
|
|
|
* sorted by attachment name. |
1953
|
|
|
* |
1954
|
|
|
* @param int $id Record ID. |
1955
|
|
|
* @param int &$sort Sort mode (used as output only). The function retrieves current sort mode from |
1956
|
|
|
* client cookie ({@link COOKIE_ATTACHMENTS_SORT}) and updates it, if it's out of valid range. |
1957
|
|
|
* @param int &$page Number of current page tab (used as output only). The function retrieves current |
1958
|
|
|
* page from client cookie ({@link COOKIE_ATTACHMENTS_PAGE}) and updates it, if it's out of valid range. |
1959
|
|
|
* @return CRecordset Recordset with list of attachments. |
1960
|
|
|
*/ |
1961
|
|
|
function attachments_list ($id, &$sort, &$page) |
1962
|
|
|
{ |
1963
|
|
|
debug_write_log(DEBUG_TRACE, '[attachments_list]'); |
1964
|
|
|
debug_write_log(DEBUG_DUMP, '[attachments_list] $id = ' . $id); |
1965
|
|
|
|
1966
|
|
|
$sort_modes = array |
1967
|
|
|
( |
1968
|
|
|
1 => 'attachment_name asc', |
1969
|
|
|
2 => 'attachment_size asc, attachment_name asc', |
1970
|
|
|
3 => 'fullname asc, username asc, attachment_name asc', |
1971
|
|
|
4 => 'event_time asc, attachment_name asc', |
1972
|
|
|
5 => 'attachment_name desc', |
1973
|
|
|
6 => 'attachment_size desc, attachment_name desc', |
1974
|
|
|
7 => 'fullname desc, username desc, attachment_name desc', |
1975
|
|
|
8 => 'event_time desc, attachment_name desc', |
1976
|
|
|
); |
1977
|
|
|
|
1978
|
|
|
$sort = try_request('sort', try_cookie(COOKIE_ATTACHMENTS_SORT)); |
1979
|
|
|
$sort = ustr2int($sort, 1, count($sort_modes)); |
1980
|
|
|
|
1981
|
|
|
$page = try_request('page', try_cookie(COOKIE_ATTACHMENTS_PAGE)); |
1982
|
|
|
$page = ustr2int($page, 1, MAXINT); |
1983
|
|
|
|
1984
|
|
|
save_cookie(COOKIE_ATTACHMENTS_SORT, $sort); |
1985
|
|
|
save_cookie(COOKIE_ATTACHMENTS_PAGE, $page); |
1986
|
|
|
|
1987
|
|
|
return dal_query('attachs/list.sql', $id, $sort_modes[$sort]); |
1988
|
|
|
} |
1989
|
|
|
|
1990
|
|
|
/** |
1991
|
|
|
* Adds new attachment to specified record. |
1992
|
|
|
* |
1993
|
|
|
* @param int $id Record ID. |
1994
|
|
|
* @param string $name Attachment name. |
1995
|
|
|
* @param array $attachfile Information about uploaded user file (see {@link http://www.php.net/features.file-upload} for details). |
1996
|
|
|
* @return int Error code: |
1997
|
|
|
* <ul> |
1998
|
|
|
* <li>{@link NO_ERROR} - attachment is successfully created</li> |
1999
|
|
|
* <li>{@link ERROR_NOT_FOUND} - record cannot be found</li> |
2000
|
|
|
* <li>{@link ERROR_ALREADY_EXISTS} - attachment with specified name already exists</li> |
2001
|
|
|
* <li>{@link ERROR_UPLOAD_INI_SIZE} - the uploaded file exceeds the {@link http://www.php.net/ini.core#ini.upload-max-filesize upload_max_filesize} directive in <i>php.ini</i></li> |
2002
|
|
|
* <li>{@link ERROR_UPLOAD_FORM_SIZE} - the uploaded file exceeds the {@link EMAIL_ATTACHMENTS_MAXSIZE}</li> |
2003
|
|
|
* <li>{@link ERROR_UPLOAD_PARTIAL} - the uploaded file was only partially uploaded</li> |
2004
|
|
|
* <li>{@link ERROR_UPLOAD_NO_FILE} - no file was uploaded</li> |
2005
|
|
|
* <li>{@link ERROR_UPLOAD_NO_TMP_DIR} - missing a temporary folder</li> |
2006
|
|
|
* <li>{@link ERROR_UPLOAD_CANT_WRITE} - failed to write file to disk</li> |
2007
|
|
|
* <li>{@link ERROR_UPLOAD_EXTENSION} - file upload stopped by extension</li> |
2008
|
|
|
* <li>{@link ERROR_UNKNOWN} - unknown failure</li> |
2009
|
|
|
* </ul> |
2010
|
|
|
*/ |
2011
|
|
|
function attachment_add ($id, $name, $attachfile) |
2012
|
|
|
{ |
2013
|
|
|
debug_write_log(DEBUG_TRACE, '[attachment_add]'); |
2014
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_add] $id = ' . $id); |
2015
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_add] $name = ' . $name); |
2016
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_add] $attachfile["name"] = ' . $attachfile['name']); |
2017
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_add] $attachfile["type"] = ' . $attachfile['type']); |
2018
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_add] $attachfile["size"] = ' . $attachfile['size']); |
2019
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_add] $attachfile["tmp_name"] = ' . $attachfile['tmp_name']); |
2020
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_add] $attachfile["error"] = ' . $attachfile['error']); |
2021
|
|
|
|
2022
|
|
|
if (ustrlen($name) == 0) |
2023
|
|
|
{ |
2024
|
|
|
debug_write_log(DEBUG_NOTICE, '[attachment_add] Attachment name is not specified.'); |
2025
|
|
|
$name = ustrcut($attachfile['name'], MAX_ATTACHMENT_NAME); |
2026
|
|
|
} |
2027
|
|
|
else |
2028
|
|
|
{ |
2029
|
|
|
if (false !== ($pos = ustrpos($attachfile['name'], '.'))) |
2030
|
|
|
{ |
2031
|
|
|
$extension = usubstr($attachfile['name'], $pos); |
2032
|
|
|
|
2033
|
|
|
if ($extension != usubstr($name, -ustrlen($extension))) |
2034
|
|
|
{ |
2035
|
|
|
$name = ustrcut($name, MAX_ATTACHMENT_NAME - ustrlen($extension)); |
2036
|
|
|
$name .= $extension; |
2037
|
|
|
} |
2038
|
|
|
} |
2039
|
|
|
} |
2040
|
|
|
|
2041
|
|
|
$record = record_find($id); |
2042
|
|
|
|
2043
|
|
|
if (!$record) |
2044
|
|
|
{ |
2045
|
|
|
debug_write_log(DEBUG_ERROR, '[attachment_add] Record cannot be found.'); |
2046
|
|
|
return ERROR_NOT_FOUND; |
2047
|
|
|
} |
2048
|
|
|
|
2049
|
|
|
$rs = dal_query('attachs/fndku.sql', $id, $name); |
2050
|
|
|
|
2051
|
|
|
if ($rs->rows != 0) |
2052
|
|
|
{ |
2053
|
|
|
debug_write_log(DEBUG_WARNING, '[attachment_add] Attachment already exists.'); |
2054
|
|
|
return ERROR_ALREADY_EXISTS; |
2055
|
|
|
} |
2056
|
|
|
|
2057
|
|
|
switch ($attachfile['error']) |
2058
|
|
|
{ |
2059
|
|
|
case UPLOAD_ERR_OK: |
2060
|
|
|
break; // nop |
2061
|
|
|
case UPLOAD_ERR_INI_SIZE: |
2062
|
|
|
return ERROR_UPLOAD_INI_SIZE; |
2063
|
|
|
case UPLOAD_ERR_FORM_SIZE: |
2064
|
|
|
return ERROR_UPLOAD_FORM_SIZE; |
2065
|
|
|
case UPLOAD_ERR_PARTIAL: |
2066
|
|
|
return ERROR_UPLOAD_PARTIAL; |
2067
|
|
|
case UPLOAD_ERR_NO_FILE: |
2068
|
|
|
return ERROR_UPLOAD_NO_FILE; |
2069
|
|
|
case UPLOAD_ERR_NO_TMP_DIR: |
2070
|
|
|
return ERROR_UPLOAD_NO_TMP_DIR; |
2071
|
|
|
case UPLOAD_ERR_CANT_WRITE: |
2072
|
|
|
return ERROR_UPLOAD_CANT_WRITE; |
2073
|
|
|
case UPLOAD_ERR_EXTENSION: |
2074
|
|
|
return ERROR_UPLOAD_EXTENSION; |
2075
|
|
|
default: |
2076
|
|
|
return ERROR_UNKNOWN; |
2077
|
|
|
} |
2078
|
|
|
|
2079
|
|
|
if ($attachfile['size'] > ATTACHMENTS_MAXSIZE * 1024) |
2080
|
|
|
{ |
2081
|
|
|
debug_write_log(DEBUG_WARNING, '[attachment_add] Attachment is too large.'); |
2082
|
|
|
return ERROR_UPLOAD_FORM_SIZE; |
2083
|
|
|
} |
2084
|
|
|
|
2085
|
|
View Code Duplication |
if (!is_uploaded_file($attachfile['tmp_name'])) |
|
|
|
|
2086
|
|
|
{ |
2087
|
|
|
debug_write_log(DEBUG_WARNING, '[attachment_add] Function "is_uploaded_file" warns that file named by "' . $attachfile['tmp_name'] . '" was not uploaded via HTTP POST.'); |
2088
|
|
|
return NO_ERROR; |
2089
|
|
|
} |
2090
|
|
|
|
2091
|
|
|
if (ATTACHMENTS_TOTALSIZE != 0) |
2092
|
|
|
{ |
2093
|
|
|
$rs = dal_query('attachs/total.sql'); |
2094
|
|
|
$total_size = $rs->fetch(0); |
2095
|
|
|
|
2096
|
|
|
if ($total_size + $attachfile['size'] > ATTACHMENTS_TOTALSIZE * 1048576) |
2097
|
|
|
{ |
2098
|
|
|
return ERROR_UPLOAD_CANT_WRITE; |
2099
|
|
|
} |
2100
|
|
|
} |
2101
|
|
|
|
2102
|
|
|
$event = event_create($id, EVENT_FILE_ATTACHED, time()); |
2103
|
|
|
|
2104
|
|
|
if (!$event) |
2105
|
|
|
{ |
2106
|
|
|
debug_write_log(DEBUG_ERROR, '[attachment_add] Event cannot be found.'); |
2107
|
|
|
return ERROR_NOT_FOUND; |
2108
|
|
|
} |
2109
|
|
|
|
2110
|
|
|
dal_query('attachs/create.sql', |
2111
|
|
|
$name, |
2112
|
|
|
$attachfile['type'], |
2113
|
|
|
$attachfile['size'], |
2114
|
|
|
$event['event_id']); |
2115
|
|
|
|
2116
|
|
|
$rs = dal_query('attachs/fndku.sql', $id, $name); |
2117
|
|
|
|
2118
|
|
|
if ($rs->rows == 0) |
2119
|
|
|
{ |
2120
|
|
|
debug_write_log(DEBUG_ERROR, '[attachment_add] Attachment cannot be found.'); |
2121
|
|
|
return ERROR_NOT_FOUND; |
2122
|
|
|
} |
2123
|
|
|
|
2124
|
|
|
$attachment_id = $rs->fetch('attachment_id'); |
2125
|
|
|
|
2126
|
|
|
$attachment_localname = ATTACHMENTS_PATH . $attachment_id; |
2127
|
|
|
|
2128
|
|
|
@move_uploaded_file($attachfile['tmp_name'], $attachment_localname); |
2129
|
|
|
|
2130
|
|
|
if (ATTACHMENTS_COMPRESSED) |
2131
|
|
|
{ |
2132
|
|
|
compressfile($attachment_localname); |
2133
|
|
|
} |
2134
|
|
|
|
2135
|
|
|
event_mail($event, $attachment_id, $name, $attachfile['type'], $attachfile['size']); |
2136
|
|
|
|
2137
|
|
|
return NO_ERROR; |
2138
|
|
|
} |
2139
|
|
|
|
2140
|
|
|
/** |
2141
|
|
|
* Removes specified attachment from its record. |
2142
|
|
|
* |
2143
|
|
|
* @param int $id Record ID. |
2144
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2145
|
|
|
* @param int $attachment_id ID of attachment to be removed. |
2146
|
|
|
* @return int Error code: |
2147
|
|
|
* <ul> |
2148
|
|
|
* <li>{@link NO_ERROR} - attachment is successfully removed</li> |
2149
|
|
|
* <li>{@link ERROR_NOT_FOUND} - attachment cannot be found</li> |
2150
|
|
|
* </ul> |
2151
|
|
|
*/ |
2152
|
|
|
function attachment_remove ($id, $permissions, $attachment_id) |
2153
|
|
|
{ |
2154
|
|
|
debug_write_log(DEBUG_TRACE, '[attachment_remove]'); |
2155
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_remove] $id = ' . $id); |
2156
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_remove] $permissions = ' . $permissions); |
2157
|
|
|
debug_write_log(DEBUG_DUMP, '[attachment_remove] $attachment_id = ' . $attachment_id); |
2158
|
|
|
|
2159
|
|
|
$attachment = attachment_find($attachment_id); |
2160
|
|
|
|
2161
|
|
|
if (!$attachment) |
2162
|
|
|
{ |
2163
|
|
|
debug_write_log(DEBUG_NOTICE, '[attachment_remove] Attachment cannot be found.'); |
2164
|
|
|
return ERROR_NOT_FOUND; |
2165
|
|
|
} |
2166
|
|
|
|
2167
|
|
|
if (($permissions & PERMIT_REMOVE_FILES) == 0) |
2168
|
|
|
{ |
2169
|
|
|
debug_write_log(DEBUG_NOTICE, '[attachment_remove] No permissions to remove this attachment.'); |
2170
|
|
|
return ERROR_NOT_FOUND; |
2171
|
|
|
} |
2172
|
|
|
|
2173
|
|
|
$event = event_create($id, EVENT_FILE_REMOVED, time(), $attachment_id); |
2174
|
|
|
|
2175
|
|
|
dal_query('attachs/remove.sql', $attachment_id); |
2176
|
|
|
|
2177
|
|
|
@unlink(ATTACHMENTS_PATH . $attachment_id); |
2178
|
|
|
|
2179
|
|
|
event_mail($event); |
2180
|
|
|
|
2181
|
|
|
return NO_ERROR; |
2182
|
|
|
} |
2183
|
|
|
|
2184
|
|
|
/** |
2185
|
|
|
* Returns {@link CRecordset DAL recordset} which contains all parent records of specified record, sorted by ID. |
2186
|
|
|
* |
2187
|
|
|
* @param int $id Record ID. |
2188
|
|
|
* @return CRecordset Recordset with list of parent records. |
2189
|
|
|
*/ |
2190
|
|
View Code Duplication |
function parents_list ($id) |
|
|
|
|
2191
|
|
|
{ |
2192
|
|
|
debug_write_log(DEBUG_TRACE, '[parents_list]'); |
2193
|
|
|
debug_write_log(DEBUG_DUMP, '[parents_list] $id = ' . $id); |
2194
|
|
|
|
2195
|
|
|
return dal_query('depends/parents.sql', $id); |
2196
|
|
|
} |
2197
|
|
|
|
2198
|
|
|
/** |
2199
|
|
|
* Returns {@link CRecordset DAL recordset} which contains all subrecords of specified record, sorted by ID. |
2200
|
|
|
* |
2201
|
|
|
* @param int $id Record ID. |
2202
|
|
|
* @return CRecordset Recordset with list of subrecords. |
2203
|
|
|
*/ |
2204
|
|
View Code Duplication |
function subrecords_list ($id) |
|
|
|
|
2205
|
|
|
{ |
2206
|
|
|
debug_write_log(DEBUG_TRACE, '[subrecords_list]'); |
2207
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecords_list] $id = ' . $id); |
2208
|
|
|
|
2209
|
|
|
return dal_query('depends/list.sql', $id); |
2210
|
|
|
} |
2211
|
|
|
|
2212
|
|
|
/** |
2213
|
|
|
* Validates subrecord information before creation. |
2214
|
|
|
* |
2215
|
|
|
* @param int $parent_id Parent record ID. |
2216
|
|
|
* @param int $subrecord_id Subrecord ID. |
2217
|
|
|
* @return int Error code: |
2218
|
|
|
* <ul> |
2219
|
|
|
* <li>{@link NO_ERROR} - data are valid</li> |
2220
|
|
|
* <li>{@link ERROR_INCOMPLETE_FORM} - at least one of required field is empty</li> |
2221
|
|
|
* <li>{@link ERROR_INVALID_INTEGER_VALUE} - subrecord ID is not a valid integer value</li> |
2222
|
|
|
* <li>{@link ERROR_RECORD_NOT_FOUND} - subrecord cannot be found</li> |
2223
|
|
|
* </ul> |
2224
|
|
|
*/ |
2225
|
|
|
function subrecord_validate ($parent_id, $subrecord_id) |
2226
|
|
|
{ |
2227
|
|
|
debug_write_log(DEBUG_TRACE, '[subrecord_validate]'); |
2228
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecord_validate] $parent_id = ' . $parent_id); |
2229
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecord_validate] $subrecord_id = ' . $subrecord_id); |
2230
|
|
|
|
2231
|
|
|
if (ustrlen($subrecord_id) == 0) |
2232
|
|
|
{ |
2233
|
|
|
debug_write_log(DEBUG_NOTICE, '[subrecord_validate] At least one required field is empty.'); |
2234
|
|
|
return ERROR_INCOMPLETE_FORM; |
2235
|
|
|
} |
2236
|
|
|
|
2237
|
|
|
if (!is_intvalue($subrecord_id)) |
2238
|
|
|
{ |
2239
|
|
|
debug_write_log(DEBUG_NOTICE, '[subrecord_validate] Invalid record ID.'); |
2240
|
|
|
return ERROR_INVALID_INTEGER_VALUE; |
2241
|
|
|
} |
2242
|
|
|
|
2243
|
|
|
if ($parent_id == intval($subrecord_id)) |
2244
|
|
|
{ |
2245
|
|
|
debug_write_log(DEBUG_NOTICE, '[subrecord_validate] Record cannot be parent of itself.'); |
2246
|
|
|
return ERROR_RECORD_NOT_FOUND; |
2247
|
|
|
} |
2248
|
|
|
|
2249
|
|
|
$record = record_find(intval($subrecord_id)); |
2250
|
|
|
|
2251
|
|
|
if (!$record) |
2252
|
|
|
{ |
2253
|
|
|
debug_write_log(DEBUG_NOTICE, '[subrecord_validate] Record not found.'); |
2254
|
|
|
return ERROR_RECORD_NOT_FOUND; |
2255
|
|
|
} |
2256
|
|
|
|
2257
|
|
|
return NO_ERROR; |
2258
|
|
|
} |
2259
|
|
|
|
2260
|
|
|
/** |
2261
|
|
|
* Adds new subrecord to specified record. |
2262
|
|
|
* |
2263
|
|
|
* @param int $parent_id Parent record ID. |
2264
|
|
|
* @param int $subrecord_id Subrecord ID. |
2265
|
|
|
* @param bool $is_dependency . |
2266
|
|
|
* @return int Error code: |
2267
|
|
|
* <ul> |
2268
|
|
|
* <li>{@link NO_ERROR} - subrecord is successfully added</li> |
2269
|
|
|
* <li>{@link ERROR_NOT_FOUND} - subrecord cannot be found</li> |
2270
|
|
|
* <li>{@link ERROR_ALREADY_EXISTS} - specified subrecord already exists</li> |
2271
|
|
|
* </ul> |
2272
|
|
|
*/ |
2273
|
|
|
function subrecord_add ($parent_id, $subrecord_id, $is_dependency) |
2274
|
|
|
{ |
2275
|
|
|
debug_write_log(DEBUG_TRACE, '[subrecord_add]'); |
2276
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecord_add] $parent_id = ' . $parent_id); |
2277
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecord_add] $subrecord_id = ' . $subrecord_id); |
2278
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecord_add] $is_dependency = ' . $is_dependency); |
2279
|
|
|
|
2280
|
|
|
$rs = dal_query('depends/fnd2.sql', $parent_id, $subrecord_id); |
2281
|
|
|
|
2282
|
|
|
if ($rs->rows != 0) |
2283
|
|
|
{ |
2284
|
|
|
debug_write_log(DEBUG_WARNING, '[subrecord_add] Subrecord already exists.'); |
2285
|
|
|
return ERROR_ALREADY_EXISTS; |
2286
|
|
|
} |
2287
|
|
|
|
2288
|
|
|
$event = event_create($parent_id, EVENT_SUBRECORD_ADDED, time(), $subrecord_id); |
2289
|
|
|
|
2290
|
|
|
if (!$event) |
2291
|
|
|
{ |
2292
|
|
|
debug_write_log(DEBUG_ERROR, '[subrecord_add] Event cannot be found.'); |
2293
|
|
|
return ERROR_NOT_FOUND; |
2294
|
|
|
} |
2295
|
|
|
|
2296
|
|
|
dal_query('depends/create.sql', |
2297
|
|
|
$parent_id, |
2298
|
|
|
$subrecord_id, |
2299
|
|
|
bool2sql($is_dependency)); |
2300
|
|
|
|
2301
|
|
|
event_mail($event); |
2302
|
|
|
|
2303
|
|
|
return NO_ERROR; |
2304
|
|
|
} |
2305
|
|
|
|
2306
|
|
|
/** |
2307
|
|
|
* Removes specified subrecord. |
2308
|
|
|
* |
2309
|
|
|
* @param int $parent_id Parent record ID. |
2310
|
|
|
* @param int $subrecord_id Subrecord ID. |
2311
|
|
|
* @return int Error code: |
2312
|
|
|
* <ul> |
2313
|
|
|
* <li>{@link NO_ERROR} - subrecord is successfully removed</li> |
2314
|
|
|
* <li>{@link ERROR_NOT_FOUND} - subrecord cannot be found</li> |
2315
|
|
|
* </ul> |
2316
|
|
|
*/ |
2317
|
|
|
function subrecord_remove ($parent_id, $subrecord_id) |
2318
|
|
|
{ |
2319
|
|
|
debug_write_log(DEBUG_TRACE, '[subrecord_remove]'); |
2320
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecord_remove] $parent_id = ' . $parent_id); |
2321
|
|
|
debug_write_log(DEBUG_DUMP, '[subrecord_remove] $subrecord_id = ' . $subrecord_id); |
2322
|
|
|
|
2323
|
|
|
$rs = dal_query('depends/fnd2.sql', $parent_id, $subrecord_id); |
2324
|
|
|
|
2325
|
|
|
if ($rs->rows == 0) |
2326
|
|
|
{ |
2327
|
|
|
debug_write_log(DEBUG_WARNING, '[subrecord_remove] Subrecord cannot be found.'); |
2328
|
|
|
return ERROR_NOT_FOUND; |
2329
|
|
|
} |
2330
|
|
|
|
2331
|
|
|
$event = event_create($parent_id, EVENT_SUBRECORD_REMOVED, time(), $subrecord_id); |
2332
|
|
|
|
2333
|
|
|
if (!$event) |
2334
|
|
|
{ |
2335
|
|
|
debug_write_log(DEBUG_ERROR, '[subrecord_remove] Event cannot be found.'); |
2336
|
|
|
return ERROR_NOT_FOUND; |
2337
|
|
|
} |
2338
|
|
|
|
2339
|
|
|
dal_query('depends/delete.sql', |
2340
|
|
|
$parent_id, |
2341
|
|
|
$subrecord_id); |
2342
|
|
|
|
2343
|
|
|
event_mail($event); |
2344
|
|
|
|
2345
|
|
|
return NO_ERROR; |
2346
|
|
|
} |
2347
|
|
|
|
2348
|
|
|
/** |
2349
|
|
|
* Determines and returns set of permissions of current user for some record. |
2350
|
|
|
* |
2351
|
|
|
* @param int $template_id ID of record's template. |
2352
|
|
|
* @param int $creator_id Author of record. |
2353
|
|
|
* @param int $responsible_id Responsible of record. |
2354
|
|
|
* @return int Set of binary flags: |
2355
|
|
|
* <ul> |
2356
|
|
|
* <li>{@link PERMIT_CREATE_RECORD} - permission to create new records</li> |
2357
|
|
|
* <li>{@link PERMIT_MODIFY_RECORD} - permission to modify records</li> |
2358
|
|
|
* <li>{@link PERMIT_POSTPONE_RECORD} - permission to postpone records</li> |
2359
|
|
|
* <li>{@link PERMIT_RESUME_RECORD} - permission to resume records</li> |
2360
|
|
|
* <li>{@link PERMIT_REASSIGN_RECORD} - permission to reassign records, which are already assigned on another person</li> |
2361
|
|
|
* <li>{@link PERMIT_REOPEN_RECORD} - permission to reopen records</li> |
2362
|
|
|
* <li>{@link PERMIT_ADD_COMMENTS} - permission to add comments</li> |
2363
|
|
|
* <li>{@link PERMIT_ATTACH_FILES} - permission to add attachments</li> |
2364
|
|
|
* <li>{@link PERMIT_REMOVE_FILES} - permission to remove attachments</li> |
2365
|
|
|
* <li>{@link PERMIT_CONFIDENTIAL_COMMENTS} - permission to add and read confidential comments</li> |
2366
|
|
|
* <li>{@link PERMIT_SEND_REMINDERS} - permission to send reminders</li> |
2367
|
|
|
* <li>{@link PERMIT_DELETE_RECORD} - permission to delete records from database</li> |
2368
|
|
|
* <li>{@link PERMIT_ADD_SUBRECORDS} - permission to add subrecords</li> |
2369
|
|
|
* <li>{@link PERMIT_REMOVE_SUBRECORDS} - permission to remove subrecords</li> |
2370
|
|
|
* <li>{@link PERMIT_VIEW_RECORD} - permission to read records</li> |
2371
|
|
|
* </ul> |
2372
|
|
|
*/ |
2373
|
|
|
function record_get_permissions ($template_id, $creator_id, $responsible_id) |
2374
|
|
|
{ |
2375
|
|
|
debug_write_log(DEBUG_TRACE, '[record_get_permissions]'); |
2376
|
|
|
debug_write_log(DEBUG_DUMP, '[record_get_permissions] $template_id = ' . $template_id); |
2377
|
|
|
debug_write_log(DEBUG_DUMP, '[record_get_permissions] $creator_id = ' . $creator_id); |
2378
|
|
|
debug_write_log(DEBUG_DUMP, '[record_get_permissions] $responsible_id = ' . $responsible_id); |
2379
|
|
|
|
2380
|
|
|
$permissions = 0; |
2381
|
|
|
|
2382
|
|
|
if (get_user_level() == USER_LEVEL_GUEST) |
2383
|
|
|
{ |
2384
|
|
|
$rs = dal_query('templates/fndid.sql', $template_id); |
2385
|
|
|
|
2386
|
|
|
if ($rs->rows != 0) |
2387
|
|
|
{ |
2388
|
|
|
if ($rs->fetch('guest_access')) |
2389
|
|
|
{ |
2390
|
|
|
$permissions = PERMIT_VIEW_RECORD; |
2391
|
|
|
} |
2392
|
|
|
} |
2393
|
|
|
} |
2394
|
|
|
else |
2395
|
|
|
{ |
2396
|
|
|
if ($_SESSION[VAR_USERID] == $creator_id || |
2397
|
|
|
$_SESSION[VAR_USERID] == $responsible_id) |
2398
|
|
|
{ |
2399
|
|
|
$permissions = PERMIT_VIEW_RECORD; |
2400
|
|
|
} |
2401
|
|
|
|
2402
|
|
|
$rs = dal_query('groups/gplist.sql', |
2403
|
|
|
$template_id, |
2404
|
|
|
$creator_id, |
2405
|
|
|
is_null($responsible_id) ? 0 : $responsible_id, |
2406
|
|
|
$_SESSION[VAR_USERID]); |
2407
|
|
|
|
2408
|
|
|
while (($row = $rs->fetch())) |
2409
|
|
|
{ |
2410
|
|
|
$permissions |= $row['perms']; |
2411
|
|
|
} |
2412
|
|
|
} |
2413
|
|
|
|
2414
|
|
|
return $permissions; |
2415
|
|
|
} |
2416
|
|
|
|
2417
|
|
|
/** |
2418
|
|
|
* Subscribes specified account to all events of specified record. |
2419
|
|
|
* |
2420
|
|
|
* @param int $record_id Record ID. |
2421
|
|
|
* @param int $account_id ID of account which is being subscribed. |
2422
|
|
|
* @param int $subscribed_by ID of account which is subscribing another one. |
2423
|
|
|
* @return int Always {@link NO_ERROR}. |
2424
|
|
|
*/ |
2425
|
|
|
function record_subscribe ($record_id, $account_id, $subscribed_by) |
2426
|
|
|
{ |
2427
|
|
|
debug_write_log(DEBUG_TRACE, '[record_subscribe]'); |
2428
|
|
|
debug_write_log(DEBUG_DUMP, '[record_subscribe] $record_id = ' . $record_id); |
2429
|
|
|
debug_write_log(DEBUG_DUMP, '[record_subscribe] $account_id = ' . $account_id); |
2430
|
|
|
debug_write_log(DEBUG_DUMP, '[record_subscribe] $subscribed_by = ' . $subscribed_by); |
2431
|
|
|
|
2432
|
|
|
dal_query('records/unsubscribe.sql', $record_id, $account_id, $subscribed_by); |
2433
|
|
|
dal_query('records/subscribe.sql', $record_id, $account_id, $subscribed_by); |
2434
|
|
|
|
2435
|
|
|
if ($account_id != $subscribed_by) |
2436
|
|
|
{ |
2437
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_subscribe] Inform about subscription.'); |
2438
|
|
|
|
2439
|
|
|
$record = record_find($record_id); |
2440
|
|
|
$account = account_find($account_id); |
2441
|
|
|
$subscriber = account_find($subscribed_by); |
2442
|
|
|
|
2443
|
|
|
$to = $account['email']; |
2444
|
|
|
|
2445
|
|
|
$rec_id = record_id($record_id, $record['template_prefix']); |
2446
|
|
|
$subject = "[{$record['project_name']}] {$rec_id}: " |
2447
|
|
|
. htmlspecialchars_decode(update_references($record['subject'], BBCODE_OFF), ENT_COMPAT); |
2448
|
|
|
|
2449
|
|
|
$event = array('event_id' => NULL, |
2450
|
|
|
'event_type' => EVENT_RECORD_SUBSCRIBED, |
2451
|
|
|
'event_param' => $subscriber['fullname']); |
2452
|
|
|
|
2453
|
|
|
$message = generate_message($record, $event, $account['locale']); |
2454
|
|
|
|
2455
|
|
|
if (EMAIL_NOTIFICATIONS_ENABLED) |
2456
|
|
|
{ |
2457
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_subscribe] Sending email.'); |
2458
|
|
|
sendmail($subscriber['fullname'], $subscriber['email'], $to, $subject, $message); |
2459
|
|
|
} |
2460
|
|
|
else |
2461
|
|
|
{ |
2462
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_subscribe] Email notifications are disabled.'); |
2463
|
|
|
} |
2464
|
|
|
} |
2465
|
|
|
|
2466
|
|
|
return NO_ERROR; |
2467
|
|
|
} |
2468
|
|
|
|
2469
|
|
|
/** |
2470
|
|
|
* Unsubscribes specified account off specified record. |
2471
|
|
|
* |
2472
|
|
|
* @param int $record_id Record ID. |
2473
|
|
|
* @param int $account_id ID of account which is being unsubscribed. |
2474
|
|
|
* @param int $subscribed_by ID of account which is unsubscribing another one. |
2475
|
|
|
* @return int Always {@link NO_ERROR}. |
2476
|
|
|
*/ |
2477
|
|
|
function record_unsubscribe ($record_id, $account_id, $subscribed_by) |
2478
|
|
|
{ |
2479
|
|
|
debug_write_log(DEBUG_TRACE, '[record_unsubscribe]'); |
2480
|
|
|
debug_write_log(DEBUG_DUMP, '[record_unsubscribe] $record_id = ' . $record_id); |
2481
|
|
|
debug_write_log(DEBUG_DUMP, '[record_unsubscribe] $account_id = ' . $account_id); |
2482
|
|
|
debug_write_log(DEBUG_DUMP, '[record_unsubscribe] $subscribed_by = ' . $subscribed_by); |
2483
|
|
|
|
2484
|
|
|
global $locale_info; |
2485
|
|
|
|
2486
|
|
|
if ($account_id == $subscribed_by) |
2487
|
|
|
{ |
2488
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_unsubscribe] Inform about unsubscription.'); |
2489
|
|
|
|
2490
|
|
|
$record = record_find($record_id); |
2491
|
|
|
$account = account_find($account_id); |
2492
|
|
|
|
2493
|
|
|
$supported_locales = array_keys($locale_info); |
2494
|
|
|
|
2495
|
|
|
foreach ($supported_locales as $locale) |
2496
|
|
|
{ |
2497
|
|
|
$to = array(); |
2498
|
|
|
$rs = dal_query('records/subscribers.sql', $record_id, $account_id, $locale); |
2499
|
|
|
|
2500
|
|
|
while (($row = $rs->fetch())) |
2501
|
|
|
{ |
2502
|
|
|
array_push($to, $row['email']); |
2503
|
|
|
} |
2504
|
|
|
|
2505
|
|
|
if (count($to) != 0) |
2506
|
|
|
{ |
2507
|
|
|
$recipients = implode(', ', array_unique($to)); |
2508
|
|
|
|
2509
|
|
|
$rec_id = record_id($record_id, $record['template_prefix']); |
2510
|
|
|
$subject = "[{$record['project_name']}] {$rec_id}: " |
2511
|
|
|
. htmlspecialchars_decode(update_references($record['subject'], BBCODE_OFF), ENT_COMPAT); |
2512
|
|
|
|
2513
|
|
|
$event = array('event_id' => NULL, |
2514
|
|
|
'event_type' => EVENT_RECORD_UNSUBSCRIBED, |
2515
|
|
|
'event_param' => $account['fullname']); |
2516
|
|
|
|
2517
|
|
|
$message = generate_message($record, $event, $locale); |
2518
|
|
|
|
2519
|
|
|
if (EMAIL_NOTIFICATIONS_ENABLED) |
2520
|
|
|
{ |
2521
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_unsubscribe] Sending email.'); |
2522
|
|
|
sendmail($account['fullname'], $account['email'], $recipients, $subject, $message); |
2523
|
|
|
} |
2524
|
|
|
else |
2525
|
|
|
{ |
2526
|
|
|
debug_write_log(DEBUG_NOTICE, '[record_unsubscribe] Email notifications are disabled.'); |
2527
|
|
|
} |
2528
|
|
|
} |
2529
|
|
|
} |
2530
|
|
|
|
2531
|
|
|
dal_query('records/unsubscribe2.sql', $record_id, $account_id); |
2532
|
|
|
} |
2533
|
|
|
else |
2534
|
|
|
{ |
2535
|
|
|
dal_query('records/unsubscribe.sql', $record_id, $account_id, $subscribed_by); |
2536
|
|
|
} |
2537
|
|
|
|
2538
|
|
|
return NO_ERROR; |
2539
|
|
|
} |
2540
|
|
|
|
2541
|
|
|
/** |
2542
|
|
|
* Checks whether specified account is subscribed to specified record. |
2543
|
|
|
* |
2544
|
|
|
* @param int $record_id Record ID. |
2545
|
|
|
* @param int $account_id Account ID. |
2546
|
|
|
* @return bool TRUE if account is subscribed, FALSE otherwise. |
2547
|
|
|
*/ |
2548
|
|
View Code Duplication |
function is_record_subscribed ($record_id, $account_id) |
|
|
|
|
2549
|
|
|
{ |
2550
|
|
|
debug_write_log(DEBUG_TRACE, '[is_record_subscribed]'); |
2551
|
|
|
debug_write_log(DEBUG_DUMP, '[is_record_subscribed] $record_id = ' . $record_id); |
2552
|
|
|
debug_write_log(DEBUG_DUMP, '[is_record_subscribed] $account_id = ' . $account_id); |
2553
|
|
|
|
2554
|
|
|
$rs = dal_query('records/fndsubsc.sql', $record_id, $account_id); |
2555
|
|
|
|
2556
|
|
|
return ($rs->rows != 0); |
2557
|
|
|
} |
2558
|
|
|
|
2559
|
|
|
/** |
2560
|
|
|
* Checks whether a specified record has reached critical age. |
2561
|
|
|
* |
2562
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2563
|
|
|
* @return bool TRUE if record's age is already critical, FALSE otherwise. |
2564
|
|
|
*/ |
2565
|
|
View Code Duplication |
function is_record_critical ($record) |
|
|
|
|
2566
|
|
|
{ |
2567
|
|
|
debug_write_log(DEBUG_TRACE, '[is_recorde_critical]'); |
2568
|
|
|
|
2569
|
|
|
return (is_null($record['closure_time']) && |
2570
|
|
|
!is_null($record['critical_age']) && |
2571
|
|
|
$record['creation_time'] + $record['critical_age'] * SECS_IN_DAY < time()); |
2572
|
|
|
} |
2573
|
|
|
|
2574
|
|
|
/** |
2575
|
|
|
* Checks whether a specified record is frozen. |
2576
|
|
|
* |
2577
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2578
|
|
|
* @return bool TRUE if record is already frozen, FALSE otherwise. |
2579
|
|
|
*/ |
2580
|
|
View Code Duplication |
function is_record_frozen ($record) |
|
|
|
|
2581
|
|
|
{ |
2582
|
|
|
debug_write_log(DEBUG_TRACE, '[is_record_frozen]'); |
2583
|
|
|
|
2584
|
|
|
return (!is_null($record['closure_time']) && |
2585
|
|
|
!is_null($record['frozen_time']) && |
2586
|
|
|
$record['closure_time'] + $record['frozen_time'] * SECS_IN_DAY < time()); |
2587
|
|
|
} |
2588
|
|
|
|
2589
|
|
|
/** |
2590
|
|
|
* Checks whether a specified record is postponed. |
2591
|
|
|
* |
2592
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2593
|
|
|
* @return bool TRUE if record is currently postponed, FALSE otherwise. |
2594
|
|
|
*/ |
2595
|
|
|
function is_record_postponed ($record) |
2596
|
|
|
{ |
2597
|
|
|
debug_write_log(DEBUG_TRACE, '[is_record_postponed]'); |
2598
|
|
|
|
2599
|
|
|
return (is_null($record['closure_time']) && |
2600
|
|
|
$record['postpone_time'] > time()); |
2601
|
|
|
} |
2602
|
|
|
|
2603
|
|
|
/** |
2604
|
|
|
* Checks whether a specified record is closed. |
2605
|
|
|
* |
2606
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2607
|
|
|
* @return bool TRUE if record is already closed, FALSE otherwise. |
2608
|
|
|
*/ |
2609
|
|
|
function is_record_closed ($record) |
2610
|
|
|
{ |
2611
|
|
|
debug_write_log(DEBUG_TRACE, '[is_record_closed]'); |
2612
|
|
|
|
2613
|
|
|
return !is_null($record['closure_time']); |
2614
|
|
|
} |
2615
|
|
|
|
2616
|
|
|
/** |
2617
|
|
|
* Checks whether a specified record was cloned from another one. |
2618
|
|
|
* |
2619
|
|
|
* @param int $id Record ID. |
2620
|
|
|
* @return int ID of original record if specified one was cloned from it, 0 otherwise. |
2621
|
|
|
*/ |
2622
|
|
View Code Duplication |
function is_record_cloned ($id) |
|
|
|
|
2623
|
|
|
{ |
2624
|
|
|
debug_write_log(DEBUG_TRACE, '[is_record_cloned]'); |
2625
|
|
|
debug_write_log(DEBUG_DUMP, '[is_record_cloned] $id = ' . $id); |
2626
|
|
|
|
2627
|
|
|
$rs = dal_query('events/fnd.sql', |
2628
|
|
|
$id, |
2629
|
|
|
EVENT_RECORD_CLONED); |
2630
|
|
|
|
2631
|
|
|
return ($rs->rows == 0 ? 0 : $rs->fetch('event_param')); |
2632
|
|
|
} |
2633
|
|
|
|
2634
|
|
|
/** |
2635
|
|
|
* Calculates number of days since the last event of specified record. |
2636
|
|
|
* |
2637
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2638
|
|
|
* @return int Number of days. |
2639
|
|
|
*/ |
2640
|
|
|
function get_record_last_event ($record) |
2641
|
|
|
{ |
2642
|
|
|
debug_write_log(DEBUG_TRACE, '[get_record_last_event]'); |
2643
|
|
|
|
2644
|
|
|
return ceil((time() - $record['change_time'] + 1) / SECS_IN_DAY); |
2645
|
|
|
} |
2646
|
|
|
|
2647
|
|
|
/** |
2648
|
|
|
* Calculates number of days since the last change of state of specified record. |
2649
|
|
|
* |
2650
|
|
|
* @param array $record Record information, as it returned by {@link records_list}. |
2651
|
|
|
* @return int Number of days. |
2652
|
|
|
*/ |
2653
|
|
|
function get_record_last_state ($record) |
2654
|
|
|
{ |
2655
|
|
|
debug_write_log(DEBUG_TRACE, '[get_record_last_state]'); |
2656
|
|
|
|
2657
|
|
|
return ceil((time() - $record['state_time'] + 1) / SECS_IN_DAY); |
2658
|
|
|
} |
2659
|
|
|
|
2660
|
|
|
/** |
2661
|
|
|
* Calculates age of specified record. |
2662
|
|
|
* |
2663
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2664
|
|
|
* @return int Age as number of days. |
2665
|
|
|
*/ |
2666
|
|
|
function get_record_age ($record) |
2667
|
|
|
{ |
2668
|
|
|
debug_write_log(DEBUG_TRACE, '[get_record_age]'); |
2669
|
|
|
|
2670
|
|
|
return (is_record_closed($record) |
2671
|
|
|
? ceil($record['closed_age'] / SECS_IN_DAY) |
2672
|
|
|
: ceil(($record['opened_age'] + 1) / SECS_IN_DAY)); |
2673
|
|
|
} |
2674
|
|
|
|
2675
|
|
|
/** |
2676
|
|
|
* Checks whether specified permissions allow to see a record. |
2677
|
|
|
* |
2678
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2679
|
|
|
* @return bool TRUE if record can be displayed, FALSE otherwise. |
2680
|
|
|
*/ |
2681
|
|
|
function can_record_be_displayed ($permissions) |
2682
|
|
|
{ |
2683
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_displayed]'); |
2684
|
|
|
|
2685
|
|
|
return ($permissions & PERMIT_VIEW_RECORD); |
2686
|
|
|
} |
2687
|
|
|
|
2688
|
|
|
/** |
2689
|
|
|
* Checks whether current user is allowed to create new record. |
2690
|
|
|
* |
2691
|
|
|
* @return bool TRUE if user is allowed to create new record, FALSE otherwise. |
2692
|
|
|
*/ |
2693
|
|
|
function can_record_be_created () |
2694
|
|
|
{ |
2695
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_created]'); |
2696
|
|
|
|
2697
|
|
|
if (get_user_level() == USER_LEVEL_GUEST) |
2698
|
|
|
{ |
2699
|
|
|
return FALSE; |
2700
|
|
|
} |
2701
|
|
|
|
2702
|
|
|
if (DATABASE_DRIVER == DRIVER_ORACLE9) |
2703
|
|
|
{ |
2704
|
|
|
$rs = dal_query('records/oracle/plist.sql', $_SESSION[VAR_USERID]); |
2705
|
|
|
} |
2706
|
|
|
else |
2707
|
|
|
{ |
2708
|
|
|
$rs = dal_query('records/plist.sql', $_SESSION[VAR_USERID]); |
2709
|
|
|
} |
2710
|
|
|
|
2711
|
|
|
return ($rs->rows != 0); |
2712
|
|
|
} |
2713
|
|
|
|
2714
|
|
|
/** |
2715
|
|
|
* Checks whether specified permissions allow to modify specified record. |
2716
|
|
|
* |
2717
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2718
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2719
|
|
|
* @return bool TRUE if record can be modified, FALSE otherwise. |
2720
|
|
|
*/ |
2721
|
|
|
function can_record_be_modified ($record, $permissions) |
2722
|
|
|
{ |
2723
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_modified]'); |
2724
|
|
|
|
2725
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2726
|
|
|
!$record['is_suspended'] && |
2727
|
|
|
!$record['is_locked'] && |
2728
|
|
|
!is_record_postponed($record) && |
2729
|
|
|
!is_record_frozen($record) && |
2730
|
|
|
($permissions & PERMIT_MODIFY_RECORD)); |
2731
|
|
|
} |
2732
|
|
|
|
2733
|
|
|
/** |
2734
|
|
|
* Checks whether specified permissions allow to delete specified record. |
2735
|
|
|
* |
2736
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2737
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2738
|
|
|
* @return bool TRUE if record can be deleted, FALSE otherwise. |
2739
|
|
|
*/ |
2740
|
|
|
function can_record_be_deleted ($record, $permissions) |
2741
|
|
|
{ |
2742
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_deleted]'); |
2743
|
|
|
|
2744
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2745
|
|
|
!$record['is_suspended'] && |
2746
|
|
|
!$record['is_locked'] && |
2747
|
|
|
!is_record_postponed($record) && |
2748
|
|
|
!is_record_frozen($record) && |
2749
|
|
|
($permissions & PERMIT_DELETE_RECORD)); |
2750
|
|
|
} |
2751
|
|
|
|
2752
|
|
|
/** |
2753
|
|
|
* Checks whether specified permissions allow to postpone specified record. |
2754
|
|
|
* |
2755
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2756
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2757
|
|
|
* @return bool TRUE if record can be postponed, FALSE otherwise. |
2758
|
|
|
*/ |
2759
|
|
View Code Duplication |
function can_record_be_postponed ($record, $permissions) |
|
|
|
|
2760
|
|
|
{ |
2761
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_postponed]'); |
2762
|
|
|
|
2763
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2764
|
|
|
!$record['is_suspended'] && |
2765
|
|
|
!$record['is_locked'] && |
2766
|
|
|
!is_record_postponed($record) && |
2767
|
|
|
is_null($record['closure_time']) && |
2768
|
|
|
($permissions & PERMIT_POSTPONE_RECORD)); |
2769
|
|
|
} |
2770
|
|
|
|
2771
|
|
|
/** |
2772
|
|
|
* Checks whether specified permissions allow to resume specified record. |
2773
|
|
|
* |
2774
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2775
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2776
|
|
|
* @return bool TRUE if record can be resumed, FALSE otherwise. |
2777
|
|
|
*/ |
2778
|
|
|
function can_record_be_resumed ($record, $permissions) |
2779
|
|
|
{ |
2780
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_resumed]'); |
2781
|
|
|
|
2782
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2783
|
|
|
!$record['is_suspended'] && |
2784
|
|
|
!$record['is_locked'] && |
2785
|
|
|
is_record_postponed($record) && |
2786
|
|
|
is_null($record['closure_time']) && |
2787
|
|
|
($permissions & PERMIT_RESUME_RECORD)); |
2788
|
|
|
} |
2789
|
|
|
|
2790
|
|
|
/** |
2791
|
|
|
* Checks whether specified permissions allow to reassign specified record. |
2792
|
|
|
* |
2793
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2794
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2795
|
|
|
* @return bool TRUE if record can be reassigned, FALSE otherwise. |
2796
|
|
|
*/ |
2797
|
|
View Code Duplication |
function can_record_be_reassigned ($record, $permissions) |
|
|
|
|
2798
|
|
|
{ |
2799
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_reassigned]'); |
2800
|
|
|
|
2801
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2802
|
|
|
!$record['is_suspended'] && |
2803
|
|
|
!$record['is_locked'] && |
2804
|
|
|
!is_record_postponed($record) && |
2805
|
|
|
is_null($record['closure_time']) && |
2806
|
|
|
!is_null($record['responsible_id']) && |
2807
|
|
|
($permissions & PERMIT_REASSIGN_RECORD)); |
2808
|
|
|
} |
2809
|
|
|
|
2810
|
|
|
/** |
2811
|
|
|
* Checks whether specified permissions allow to reopen specified record. |
2812
|
|
|
* |
2813
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2814
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2815
|
|
|
* @return bool TRUE if record can be reopened, FALSE otherwise. |
2816
|
|
|
*/ |
2817
|
|
|
function can_record_be_reopened ($record, $permissions) |
2818
|
|
|
{ |
2819
|
|
|
debug_write_log(DEBUG_TRACE, '[can_record_be_reopened]'); |
2820
|
|
|
|
2821
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2822
|
|
|
!$record['is_suspended'] && |
2823
|
|
|
!$record['is_locked'] && |
2824
|
|
|
!is_null($record['closure_time']) && |
2825
|
|
|
($permissions & PERMIT_REOPEN_RECORD)); |
2826
|
|
|
} |
2827
|
|
|
|
2828
|
|
|
/** |
2829
|
|
|
* Checks whether it's allowed to change state of specified record. |
2830
|
|
|
* |
2831
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2832
|
|
|
* @return bool TRUE if state of the record can be changed, FALSE otherwise. |
2833
|
|
|
*/ |
2834
|
|
|
function can_state_be_changed ($record) |
2835
|
|
|
{ |
2836
|
|
|
debug_write_log(DEBUG_TRACE, '[can_state_be_changed]'); |
2837
|
|
|
|
2838
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2839
|
|
|
!$record['is_suspended'] && |
2840
|
|
|
!$record['is_locked'] && |
2841
|
|
|
!is_record_postponed($record) && |
2842
|
|
|
is_null($record['closure_time'])); |
2843
|
|
|
} |
2844
|
|
|
|
2845
|
|
|
/** |
2846
|
|
|
* Checks whether specified permissions allow to post a comment in specified record. |
2847
|
|
|
* |
2848
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2849
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2850
|
|
|
* @return bool TRUE if comment can be posted, FALSE otherwise. |
2851
|
|
|
*/ |
2852
|
|
View Code Duplication |
function can_comment_be_added ($record, $permissions) |
|
|
|
|
2853
|
|
|
{ |
2854
|
|
|
debug_write_log(DEBUG_TRACE, '[can_comment_be_added]'); |
2855
|
|
|
|
2856
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2857
|
|
|
!$record['is_suspended'] && |
2858
|
|
|
!$record['is_locked'] && |
2859
|
|
|
!is_record_frozen($record) && |
2860
|
|
|
($permissions & (PERMIT_ADD_COMMENTS | PERMIT_CONFIDENTIAL_COMMENTS))); |
2861
|
|
|
} |
2862
|
|
|
|
2863
|
|
|
/** |
2864
|
|
|
* Checks whether specified permissions allow to attach file to specified record. |
2865
|
|
|
* |
2866
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2867
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2868
|
|
|
* @return bool TRUE if file can be attached, FALSE otherwise. |
2869
|
|
|
*/ |
2870
|
|
View Code Duplication |
function can_file_be_attached ($record, $permissions) |
|
|
|
|
2871
|
|
|
{ |
2872
|
|
|
debug_write_log(DEBUG_TRACE, '[can_file_be_attached]'); |
2873
|
|
|
|
2874
|
|
|
if (ATTACHMENTS_ENABLED == 0) |
2875
|
|
|
{ |
2876
|
|
|
return FALSE; |
2877
|
|
|
} |
2878
|
|
|
|
2879
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2880
|
|
|
!$record['is_suspended'] && |
2881
|
|
|
!$record['is_locked'] && |
2882
|
|
|
!is_record_frozen($record) && |
2883
|
|
|
($permissions & PERMIT_ATTACH_FILES)); |
2884
|
|
|
} |
2885
|
|
|
|
2886
|
|
|
/** |
2887
|
|
|
* Checks whether specified permissions allow to remove attached file from specified record. |
2888
|
|
|
* |
2889
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2890
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2891
|
|
|
* @return bool TRUE if attached file can be removed, FALSE otherwise. |
2892
|
|
|
*/ |
2893
|
|
View Code Duplication |
function can_file_be_removed ($record) |
|
|
|
|
2894
|
|
|
{ |
2895
|
|
|
debug_write_log(DEBUG_TRACE, '[can_file_be_removed]'); |
2896
|
|
|
|
2897
|
|
|
if (ATTACHMENTS_ENABLED == 0) |
2898
|
|
|
{ |
2899
|
|
|
return FALSE; |
2900
|
|
|
} |
2901
|
|
|
|
2902
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2903
|
|
|
!$record['is_suspended'] && |
2904
|
|
|
!$record['is_locked'] && |
2905
|
|
|
!is_record_frozen($record)); |
2906
|
|
|
} |
2907
|
|
|
|
2908
|
|
|
/** |
2909
|
|
|
* Checks whether specified permissions allow to add subrecord to specified record. |
2910
|
|
|
* |
2911
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2912
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2913
|
|
|
* @return bool TRUE if subrecord can be added, FALSE otherwise. |
2914
|
|
|
*/ |
2915
|
|
|
function can_subrecord_be_added ($record, $permissions) |
2916
|
|
|
{ |
2917
|
|
|
debug_write_log(DEBUG_TRACE, '[can_subrecord_be_added]'); |
2918
|
|
|
|
2919
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2920
|
|
|
!$record['is_suspended'] && |
2921
|
|
|
!$record['is_locked'] && |
2922
|
|
|
!is_record_postponed($record) && |
2923
|
|
|
!is_record_frozen($record) && |
2924
|
|
|
($permissions & PERMIT_ADD_SUBRECORDS)); |
2925
|
|
|
} |
2926
|
|
|
|
2927
|
|
|
/** |
2928
|
|
|
* Checks whether specified permissions allow to remove subrecord from specified record. |
2929
|
|
|
* |
2930
|
|
|
* @param array $record Record information, as it returned by {@link record_find}. |
2931
|
|
|
* @param int $permissions User permissions (see also {@link record_get_permissions}). |
2932
|
|
|
* @return bool TRUE if subrecord can be removed, FALSE otherwise. |
2933
|
|
|
*/ |
2934
|
|
View Code Duplication |
function can_subrecord_be_removed ($record, $permissions) |
|
|
|
|
2935
|
|
|
{ |
2936
|
|
|
debug_write_log(DEBUG_TRACE, '[can_subrecord_be_removed]'); |
2937
|
|
|
|
2938
|
|
|
$rs = dal_query('depends/list.sql', $record['record_id']); |
2939
|
|
|
|
2940
|
|
|
return (get_user_level() != USER_LEVEL_GUEST && |
2941
|
|
|
!$record['is_suspended'] && |
2942
|
|
|
!$record['is_locked'] && |
2943
|
|
|
!is_record_postponed($record) && |
2944
|
|
|
!is_record_frozen($record) && |
2945
|
|
|
($permissions & PERMIT_REMOVE_SUBRECORDS) && |
2946
|
|
|
($rs->rows != 0)); |
2947
|
|
|
} |
2948
|
|
|
|
2949
|
|
|
/** |
2950
|
|
|
* Update specified {@link FIELD_TYPE_STRING string} or {@link FIELD_TYPE_MULTILINED multilined} value. |
2951
|
|
|
* |
2952
|
|
|
* @param string $value {@link FIELD_TYPE_STRING String} or {@link FIELD_TYPE_MULTILINED multilined} value to be processed. |
2953
|
|
|
* @param int $bbcode_mode BBCode processing mode: |
2954
|
|
|
* <ul> |
2955
|
|
|
* <li>{@link BBCODE_OFF} - no BBCode processing, all tags are hidden<li> |
2956
|
|
|
* <li>{@link BBCODE_SEARCH_ONLY} - only search tags are processed<li> |
2957
|
|
|
* <li>{@link BBCODE_MINIMUM} - only basic formatting is processed<li> |
2958
|
|
|
* <li>{@link BBCODE_ALL} - all available tags are processed<li> |
2959
|
|
|
* </ul> |
2960
|
|
|
* @param string $regex_search Search PCRE to transform field values. |
2961
|
|
|
* @param string $regex_replace Replace PCRE to transform field values. |
2962
|
|
|
* @return string Processed input value. |
2963
|
|
|
*/ |
2964
|
|
|
function update_references ($value, $bbcode_mode = BBCODE_ALL, $regex_search = NULL, $regex_replace = NULL) |
2965
|
|
|
{ |
2966
|
|
|
debug_write_log(DEBUG_TRACE, '[update_references]'); |
2967
|
|
|
debug_write_log(DEBUG_DUMP, '[update_references] $value = ' . $value); |
2968
|
|
|
debug_write_log(DEBUG_DUMP, '[update_references] $bbcode_mode = ' . $bbcode_mode); |
2969
|
|
|
debug_write_log(DEBUG_DUMP, '[update_references] $regex_search = ' . $regex_search); |
2970
|
|
|
debug_write_log(DEBUG_DUMP, '[update_references] $regex_replace = ' . $regex_replace); |
2971
|
|
|
|
2972
|
|
|
// Transform values with regex specified for current field. |
2973
|
|
|
if (ustrlen($regex_search) != 0 && ustrlen($regex_replace) != 0) |
2974
|
|
|
{ |
2975
|
|
|
debug_write_log(DEBUG_NOTICE, '[update_references] Regex is specified for this field.'); |
2976
|
|
|
$value = preg_replace("/{$regex_search}/isu", $regex_replace, $value); |
2977
|
|
|
} |
2978
|
|
|
|
2979
|
|
|
// Strip special HTML characters. |
2980
|
|
|
$value = ustr2html($value); |
2981
|
|
|
|
2982
|
|
|
// Transform "rec#<number>" strings into BBCode [url] tags |
2983
|
|
|
$matches = array(); |
2984
|
|
|
|
2985
|
|
|
if (preg_match_all('/(rec#(\d+))/iu', $value, $matches, PREG_SET_ORDER)) |
2986
|
|
|
{ |
2987
|
|
|
debug_write_log(DEBUG_NOTICE, '[update_references] "rec#" is found.'); |
2988
|
|
|
|
2989
|
|
|
foreach ($matches as $match) |
2990
|
|
|
{ |
2991
|
|
|
$id = (int)$match[2]; |
2992
|
|
|
|
2993
|
|
|
if ($id != 0) |
2994
|
|
|
{ |
2995
|
|
|
$record = record_find($id); |
2996
|
|
|
|
2997
|
|
|
if ($record) |
2998
|
|
|
{ |
2999
|
|
|
$replace = '[url=view.php?id=' . $id . ']' . record_id($id, $record['template_prefix']) . '[/url]'; |
3000
|
|
|
$value = ustr_replace($match[1], $replace, $value); |
3001
|
|
|
} |
3002
|
|
|
} |
3003
|
|
|
} |
3004
|
|
|
} |
3005
|
|
|
|
3006
|
|
|
// Remove non-Unix EOLs. |
3007
|
|
|
$value = ustr_replace("\r", NULL, $value); |
3008
|
|
|
|
3009
|
|
|
// Trim extra EOLs inside "[code]" blocks. |
3010
|
|
|
$value = ustr_replace("[code]\n", "[code]", $value); |
3011
|
|
|
$value = ustr_replace("\n[/code]", "[/code]", $value); |
3012
|
|
|
|
3013
|
|
|
// Replace newline characters with "%br;". |
3014
|
|
|
$value = ustr_replace("\n", '%br;', $value); |
3015
|
|
|
|
3016
|
|
|
// Process BBCode tags. |
3017
|
|
|
$search_text = ($_SESSION[VAR_SEARCH_MODE] ? $_SESSION[VAR_SEARCH_TEXT] : NULL); |
3018
|
|
|
$value = bbcode2xml($value, $bbcode_mode, $search_text); |
3019
|
|
|
|
3020
|
|
|
debug_write_log(DEBUG_DUMP, '[update_references] return = ' . $value); |
3021
|
|
|
|
3022
|
|
|
return $value; |
3023
|
|
|
} |
3024
|
|
|
|
3025
|
|
|
?> |
3026
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.