1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved |
4
|
|
|
* |
5
|
|
|
* This file is a part of Codendi. |
6
|
|
|
* |
7
|
|
|
* Codendi is free software; you can redistribute it and/or modify |
8
|
|
|
* it under the terms of the GNU General Public License as published by |
9
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
10
|
|
|
* (at your option) any later version. |
11
|
|
|
* |
12
|
|
|
* Codendi is distributed in the hope that it will be useful, |
13
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15
|
|
|
* GNU General Public License for more details. |
16
|
|
|
* |
17
|
|
|
* You should have received a copy of the GNU General Public License |
18
|
|
|
* along with Codendi. If not, see <http://www.gnu.org/licenses/>. |
19
|
|
|
*/ |
20
|
|
|
require_once('common/tracker/ArtifactField.class.php'); |
21
|
|
|
|
22
|
|
|
|
23
|
|
|
// Sort by place result |
24
|
|
|
function art_field_factory_cmp_place($field1, $field2) { |
25
|
|
|
if ($field1->getPlace() < $field2->getPlace()) |
26
|
|
|
return -1; |
27
|
|
|
else if ($field1->getPlace() > $field2->getPlace()) |
28
|
|
|
return 1; |
29
|
|
|
return 0; |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
class ArtifactFieldFactory extends Error { |
33
|
|
|
|
34
|
|
|
// The artifact type object |
35
|
|
|
var $ArtifactType; |
36
|
|
|
|
37
|
|
|
// The fields array indexed by name |
38
|
|
|
var $USAGE_BY_NAME; |
39
|
|
|
|
40
|
|
|
// The fields array indexed by id |
41
|
|
|
var $USAGE_BY_ID; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Constructor. |
45
|
|
|
* |
46
|
|
|
* @param ArtifactType: the artifact type object |
47
|
|
|
* @return boolean success. |
48
|
|
|
*/ |
49
|
|
|
function ArtifactFieldFactory(&$ArtifactType) { |
50
|
|
|
global $Language; |
51
|
|
|
|
52
|
|
|
// Error constructor |
53
|
|
|
$this->Error(); |
54
|
|
|
|
55
|
|
|
if (!$ArtifactType || !is_object($ArtifactType)) { |
56
|
|
|
$this->setError($Language->getText('tracker_common_canned','not_valid')); |
57
|
|
|
return false; |
58
|
|
|
} |
59
|
|
|
if ($ArtifactType->isError()) { |
60
|
|
|
$this->setError('ArtifactFieldFactory: '.$ArtifactType->getErrorMessage()); |
61
|
|
|
return false; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
$this->ArtifactType = $ArtifactType; |
65
|
|
|
|
66
|
|
|
$this->USAGE_BY_NAME = array(); |
67
|
|
|
$this->USAGE_BY_ID = array(); |
68
|
|
|
|
69
|
|
|
$this->fetchData($this->ArtifactType->getID()); |
70
|
|
|
|
71
|
|
|
return true; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Retrieve the fields associated with an artifact type |
76
|
|
|
* |
77
|
|
|
* @param group_artifact_id: the artifact type id |
78
|
|
|
* @return boolean success. |
79
|
|
|
*/ |
80
|
|
|
function fetchData($group_artifact_id) { |
81
|
|
|
|
82
|
|
|
$sql='SELECT af.field_id, field_name, display_type, data_type, '. |
83
|
|
|
'display_size,label, description,scope,required,empty_ok,keep_history,special, '. |
84
|
|
|
'value_function,'. |
85
|
|
|
'af.group_artifact_id, use_it, place, default_value, field_set_id '. |
86
|
|
|
'FROM artifact_field_usage afu, artifact_field af '. |
87
|
|
|
'WHERE afu.group_artifact_id='. db_ei($group_artifact_id) .' '. |
88
|
|
|
'AND afu.field_id=af.field_id AND af.group_artifact_id='. db_ei($group_artifact_id) ; |
89
|
|
|
|
90
|
|
|
//echo $sql; |
91
|
|
|
|
92
|
|
|
$res = db_query($sql); |
93
|
|
|
|
94
|
|
|
// Now put all used fields in a global array for faster access |
95
|
|
|
// Index both by field_name and field_id |
96
|
|
|
while ($field_array = db_fetch_array($res)) { |
97
|
|
|
//echo $field_array['field_name']."<br>"; |
98
|
|
|
$this->USAGE_BY_ID[$field_array['field_id']] = new ArtifactField(); |
99
|
|
|
$obj = $this->USAGE_BY_ID[$field_array['field_id']]; |
100
|
|
|
$obj->setFromArray($field_array); |
101
|
|
|
$this->USAGE_BY_ID[$field_array['field_id']] = $obj; |
102
|
|
|
|
103
|
|
|
$this->USAGE_BY_NAME[$field_array['field_name']] = new ArtifactField(); |
104
|
|
|
$obj = $this->USAGE_BY_NAME[$field_array['field_name']]; |
105
|
|
|
$obj->setFromArray($field_array); |
106
|
|
|
$this->USAGE_BY_NAME[$field_array['field_name']] = $obj; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
// rewind internal pointer of global arrays |
110
|
|
|
reset($this->USAGE_BY_ID); |
111
|
|
|
reset($this->USAGE_BY_NAME); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Get the field object using his name |
116
|
|
|
* |
117
|
|
|
* @param field_name: the field name |
118
|
|
|
* @return ArtifactField object |
119
|
|
|
*/ |
120
|
|
|
function getFieldFromName($field_name) { |
121
|
|
|
$field = isset($this->USAGE_BY_NAME[$field_name])?$this->USAGE_BY_NAME[$field_name]:false; |
122
|
|
|
return $field; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Get the field object using his id |
127
|
|
|
* |
128
|
|
|
* @param field_id: the field id |
129
|
|
|
* @return ArtifactField object |
130
|
|
|
*/ |
131
|
|
|
function getFieldFromId($field_id) { |
132
|
|
|
return isset($this->USAGE_BY_ID[$field_id])?$this->USAGE_BY_ID[$field_id]:null; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Return all the fields used |
137
|
|
|
* |
138
|
|
|
* @return array |
139
|
|
|
*/ |
140
|
|
|
function getAllUsedFields() { |
141
|
|
|
|
142
|
|
|
$result_fields = array(); |
143
|
|
|
reset($this->USAGE_BY_NAME); |
144
|
|
|
|
145
|
|
|
while (list($key,$field) = each($this->USAGE_BY_NAME) ) { |
146
|
|
|
if ( $field->getUseIt() == 1 ) { |
147
|
|
|
$result_fields[$key] = $field; |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
uasort($result_fields,"art_field_factory_cmp_place"); |
152
|
|
|
return $result_fields; |
153
|
|
|
|
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Return all the fields unused |
158
|
|
|
* |
159
|
|
|
* @return array |
160
|
|
|
*/ |
161
|
|
|
function getAllUnusedFields() { |
162
|
|
|
|
163
|
|
|
$result_fields = array(); |
164
|
|
|
reset($this->USAGE_BY_NAME); |
165
|
|
|
|
166
|
|
|
while (list($key,$field) = each($this->USAGE_BY_NAME) ) { |
167
|
|
|
if ( $field->getUseIt() == 0 ) { |
168
|
|
|
$result_fields[$key] = $field; |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
uasort($result_fields,"art_field_factory_cmp_place"); |
173
|
|
|
return $result_fields; |
174
|
|
|
|
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* |
179
|
|
|
* Returns the list of field names in the HTML Form corresponding to a |
180
|
|
|
* field used by this project |
181
|
|
|
* |
182
|
|
|
* |
183
|
|
|
* @return array |
184
|
|
|
*/ |
185
|
|
|
function extractFieldList($post_method=true,$prefix=null) { |
186
|
|
|
|
187
|
|
|
global $HTTP_GET_VARS, $HTTP_POST_VARS; |
188
|
|
|
$request =& HTTPRequest::instance(); |
189
|
|
|
|
190
|
|
|
$vfl = array(); |
191
|
|
|
if ($post_method) { |
192
|
|
|
reset($HTTP_POST_VARS); |
193
|
|
|
while ( list($key, $val) = each($HTTP_POST_VARS)) { |
|
|
|
|
194
|
|
|
//verify if the prefix param is given and cut the |
195
|
|
|
//prefix from the key |
196
|
|
|
if ($prefix != null) { |
197
|
|
|
$pos = strpos($key,$prefix); |
198
|
|
|
if (!is_bool($pos) && $pos == 0) { |
199
|
|
|
$postfix = substr($key, strlen($prefix)); |
200
|
|
|
if (isset($this->USAGE_BY_NAME[$postfix])) { |
201
|
|
|
$vfl[$postfix] = $request->get($key); |
202
|
|
|
} |
203
|
|
|
} |
204
|
|
|
} else { |
205
|
|
|
if (isset($this->USAGE_BY_NAME[$key])) { |
206
|
|
|
$vfl[$key] = $request->get($key); |
207
|
|
|
//echo "Accepted key = ".$key." val = $val<BR>"; |
208
|
|
|
} else { |
209
|
|
|
// we add operator for date filtering (used for masschange) |
210
|
|
|
// the field present in HTTP_POST_VARS is named like [$field_name]_op |
211
|
|
|
if ((isset($this->USAGE_BY_NAME[substr($key, 0, strlen($key)-strlen('_op'))]) && substr($key, -3) == '_op') || |
212
|
|
|
(isset($this->USAGE_BY_NAME[substr($key, 0, strlen($key)-strlen('_end'))]) && substr($key, -4) == '_end')) { |
213
|
|
|
$vfl[$key] = $request->get($key); |
214
|
|
|
} else { |
215
|
|
|
//echo "Rejected key = ".$key." val = $val<BR>"; |
216
|
|
|
} |
217
|
|
|
} |
218
|
|
|
} |
219
|
|
|
} |
220
|
|
|
} else { |
221
|
|
|
reset($HTTP_GET_VARS); |
222
|
|
|
while ( list($key, $val) = each($HTTP_GET_VARS)) { |
|
|
|
|
223
|
|
|
if (isset($this->USAGE_BY_NAME[$key])) { |
224
|
|
|
$vfl[$key] = $request->get($key); |
225
|
|
|
//echo "Accepted key = ".$key." val = $val<BR>"; |
226
|
|
|
} else { |
227
|
|
|
//echo "Rejected key = ".$key." val = $val<BR>"; |
228
|
|
|
} |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Hack to manage the case when the target is a mandatory multiple select list. |
235
|
|
|
* |
236
|
|
|
* Without this fix we are able to by pass the mandatory checking (ie user can submit artifact with |
237
|
|
|
* field value == none and codendi doesn't raise any error. |
238
|
|
|
* This bad behaviour comes from the way the submitted values are checked: |
239
|
|
|
* The code above relies on what is submitted by the user, it build the list of fields |
240
|
|
|
* from what the user submitted, later on it will check if the values are correct. |
241
|
|
|
* |
242
|
|
|
* For lists, it check against "none" value: if none is present but "allow empty value" |
243
|
|
|
* forbidden, it raises an error. It works because None is always present and is the default |
244
|
|
|
* value (except if configured by admin to another value). |
245
|
|
|
* But when there are dependencies, the none value disapear. so there is no longer any selected |
246
|
|
|
* value in the field (for multi select box). So when the code above populate the array of |
247
|
|
|
* submitted values, the multi select box is not present (because no value is submitted). |
248
|
|
|
* Later on, "checkEmptyValues" or field dependencies constraints are not checked because those |
249
|
|
|
* 2 methods rely on what this method (extractFieldList) returns. |
250
|
|
|
* |
251
|
|
|
* So, to make a long story short: in order to make everything work, the code below loop over |
252
|
|
|
* all used fields and if one field is missing in $vfl, it adds it with empty value. |
253
|
|
|
* |
254
|
|
|
* Note: mass change is not supported yet. |
255
|
|
|
* |
256
|
|
|
* @see src/www/tracker/include/ArtifactHtml.class.php#displayAdd |
257
|
|
|
*/ |
258
|
|
|
$user = UserManager::instance()->getCurrentUser(); |
259
|
|
|
foreach ($this->getAllUsedFields() as $field) { |
260
|
|
|
// if ( (!$field->isSpecial() || $field->getName()=='summary' || $field->getName()=='details') ) { |
261
|
|
|
// The test here restrict to multiselect box but as I have no idea of the potential |
262
|
|
|
// impact of doing it on all possible fields, it's more safe |
263
|
|
|
if ( $field->getDisplayType() == 'MB') { |
264
|
|
|
if (($request->get('func') == 'postadd' && $field->userCanSubmit($this->ArtifactType->getGroupId(), $this->ArtifactType->getID(), $user->getId())) |
265
|
|
|
|| ($request->get('func') == 'postmod' && $field->userCanUpdate($this->ArtifactType->getGroupId(), $this->ArtifactType->getID(), $user->getId())) |
266
|
|
|
) { |
267
|
|
|
if (!isset($vfl[$field->field_name])) { |
268
|
|
|
$vfl[$field->field_name] = ''; |
269
|
|
|
} |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
return($vfl); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* |
279
|
|
|
* Check whether empty values are allowed for the bug fields |
280
|
|
|
* |
281
|
|
|
* @param Array $field_array associative array of field_name -> value |
282
|
|
|
* @param Boolean $showFeedback default value set to true, manage the display or not of the error message with reference to the field label |
283
|
|
|
* |
284
|
|
|
* @return boolean |
285
|
|
|
*/ |
286
|
|
|
function checkEmptyFields($field_array, $showFeedback = true) { |
287
|
|
|
global $Language; |
288
|
|
|
|
289
|
|
|
$bad_fields = array(); |
290
|
|
|
reset($field_array); |
291
|
|
|
while ( list($key, $val) = each($field_array)) { |
292
|
|
|
//Those fields are automatically filled out |
293
|
|
|
if ($key != 'artifact_id' && $key != 'open_date' && $key != 'last_update_date') { |
294
|
|
|
$field = $this->getFieldFromName($key); |
295
|
|
|
if ( $field) { |
296
|
|
|
if ($field->isMultiSelectBox()) { |
297
|
|
|
$is_empty = (implode(",",$val)=="100"); |
298
|
|
|
} else { |
299
|
|
|
$is_empty = ( ($field->isSelectBox()) ? ($val==100) : ($val=='')); |
300
|
|
|
} |
301
|
|
|
if ( $is_empty && !$field->isEmptyOk()) { |
302
|
|
|
$bad_fields[] = $field->getLabel(); |
303
|
|
|
} |
304
|
|
|
} |
305
|
|
|
} |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
if (count($bad_fields) > 0) { |
309
|
|
|
$hp = Codendi_HTMLPurifier::instance(); |
310
|
|
|
$bad_fields_escaped = array(); |
311
|
|
|
foreach($bad_fields as $f) { |
312
|
|
|
$bad_fields_escaped[] = $hp->purify(SimpleSanitizer::unsanitize($f), CODENDI_PURIFIER_CONVERT_HTML); |
313
|
|
|
} |
314
|
|
|
if ($showFeedback) { |
315
|
|
|
$GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_field_factory','missing',join(', ',$bad_fields_escaped)), CODENDI_PURIFIER_DISABLED); |
316
|
|
|
$this->setError($Language->getText('tracker_common_field_factory','missing',join(', ',$bad_fields))); |
317
|
|
|
} |
318
|
|
|
return false; |
319
|
|
|
} else { |
320
|
|
|
return true; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* return all the fields (+ their default value) |
328
|
|
|
* of this tracker that have not been showed to the user |
329
|
|
|
* during the artifact creation |
330
|
|
|
*/ |
331
|
|
|
function getAllFieldsNotShownOnAdd() { |
332
|
|
|
$result_fields = array(); |
333
|
|
|
reset($this->USAGE_BY_NAME); |
334
|
|
|
|
335
|
|
|
while (list($key,$field) = each($this->USAGE_BY_NAME) ) { |
336
|
|
|
if ( $field->getUseIt() == 1 && |
337
|
|
|
!$field->userCanSubmit($this->ArtifactType->Group->getID(),$this->ArtifactType->getID())) { |
338
|
|
|
$result_fields[$key] = $field->getDefaultValue(); |
339
|
|
|
} |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
return $result_fields; |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* Returns all the fields of this tracker that are contained in the field set of id $fieldset_id |
347
|
|
|
* |
348
|
|
|
* @param int $fieldset_id the id of the field set |
349
|
|
|
* @return array{ArtifactField} the array of the ArtifactField objects contained in the fieldset |
|
|
|
|
350
|
|
|
*/ |
351
|
|
|
function getFieldsContainedInFieldSet($fieldset_id) { |
352
|
|
|
$fields_contained_in_fieldset = array(); |
353
|
|
|
$sql = "SELECT af.field_id |
354
|
|
|
FROM artifact_field af, artifact_field_usage afu |
355
|
|
|
WHERE af.field_set_id=". db_ei($fieldset_id) ." AND |
356
|
|
|
af.group_artifact_id=". db_ei($this->ArtifactType->getID()) ." AND |
357
|
|
|
afu.group_artifact_id=". db_ei($this->ArtifactType->getID()) ." AND |
358
|
|
|
afu.field_id=af.field_id |
359
|
|
|
ORDER BY afu.place ASC"; |
360
|
|
|
$res = db_query($sql); |
361
|
|
|
while ($field_array = db_fetch_array($res)) { |
362
|
|
|
$current_field = $this->getFieldFromId($field_array['field_id']); |
363
|
|
|
$fields_contained_in_fieldset[$current_field->getID()] = $current_field; |
364
|
|
|
} |
365
|
|
|
return $fields_contained_in_fieldset; |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* param $ug: the ugroup that we are searching for |
371
|
|
|
* param $atid_dest: all groups that do not have this tracker are foreign groups |
372
|
|
|
* return name of $ug if it is a foreign group else return false |
373
|
|
|
*/ |
374
|
|
|
function _getForeignUgroupName($ug,$atid_dest) { |
375
|
|
|
$db_res = db_query("SELECT ugroup.name FROM ugroup,artifact_group_list agl ". |
376
|
|
|
"WHERE ugroup.ugroup_id='". db_ei($ug) ."' ". |
377
|
|
|
"AND agl.group_artifact_id='". db_ei($atid_dest) ."' ". |
378
|
|
|
"AND ugroup.group_id!=agl.group_id"); |
379
|
|
|
if ($name_array = db_fetch_array($db_res)) { |
380
|
|
|
return $name_array['name']; |
381
|
|
|
} else { |
382
|
|
|
return false; |
383
|
|
|
} |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* |
389
|
|
|
* Copy all the fields informations from this artifacttype to another. |
390
|
|
|
* |
391
|
|
|
* @param atid_source: source tracker |
392
|
|
|
* @param atid_dest: destination tracker |
393
|
|
|
* @param mapping_fieldset_array: mapping array between source fieldsets and dest ones $mapping_fieldset_array[$source_fieldset_id] = $dest_fieldset_id |
394
|
|
|
* |
395
|
|
|
* @return boolean |
396
|
|
|
*/ |
397
|
|
|
function copyFields($atid_dest, $mapping_fieldset_array,$ugroup_mapping=false) { |
398
|
|
|
global $Language; |
399
|
|
|
|
400
|
|
|
reset($this->USAGE_BY_NAME); |
401
|
|
|
|
402
|
|
|
while (list($key,$field) = each($this->USAGE_BY_NAME) ) { |
|
|
|
|
403
|
|
|
//$field = new ArtifactField(); |
404
|
|
|
//$field->setFromArray($field_array); |
405
|
|
|
|
406
|
|
|
|
407
|
|
|
//test if we got as value_function a ugroup that does not exist in the dest group |
408
|
|
|
$val_function = $field->getValueFunction(); |
409
|
|
|
$dest_val_func = array(); |
410
|
|
|
|
411
|
|
|
//go through all group binds |
412
|
|
|
if (!empty($val_function)) { |
413
|
|
|
|
414
|
|
|
foreach ($val_function as $val_func) { |
415
|
|
|
$ug = $field->isUgroupValueFunction($val_func); |
416
|
|
|
if ($ug !== false) { |
417
|
|
|
|
418
|
|
|
if ($ugroup_mapping==false || empty($ugroup_mapping)) { |
|
|
|
|
419
|
|
|
|
420
|
|
|
//avoid that when copying a tracker only (not copying a template with all trackers) |
421
|
|
|
//that we use ugroups from foreign groups in the value_function |
422
|
|
|
$name = $this->_getForeignUgroupName($ug,$atid_dest); |
423
|
|
|
if ($name !== false) { |
424
|
|
|
//don't copy this ugroup |
425
|
|
|
$GLOBALS['Response']->addFeedback('warning', $Language->getText('tracker_common_field_factory','ugroup_not_exist',array($field->getLabel(),$name))); |
426
|
|
|
} else { |
427
|
|
|
$dest_val_func[] = "ugroup_$ug"; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
} else { |
431
|
|
|
if (isset($ugroup_mapping[$ug])) { |
432
|
|
|
$dest_ug = $ugroup_mapping[$ug]; |
433
|
|
|
$dest_val_func[] = "ugroup_".$dest_ug; |
434
|
|
|
} else { |
435
|
|
|
$name = $this->_getForeignUgroupName($ug,$atid_dest); |
436
|
|
|
if ($name !== false) { |
437
|
|
|
//don't copy this ugroup |
438
|
|
|
$GLOBALS['Response']->addFeedback('warning', $Language->getText('tracker_common_field_factory','ugroup_not_exist',array($field->getLabel(),$name))); |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
} |
442
|
|
|
} |
443
|
|
|
} else { |
444
|
|
|
//this is the case where we have |
445
|
|
|
//artifact_submitters,group_members,group_admins,tracker_admins |
446
|
|
|
$dest_val_func[] = $val_func; |
447
|
|
|
} |
448
|
|
|
} |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
|
452
|
|
|
$sql_insert = 'INSERT INTO artifact_field VALUES |
453
|
|
|
('. db_ei($field->getID()) .','. db_ei($atid_dest) .', '. db_ei($mapping_fieldset_array[$field->getFieldSetID()]) . |
454
|
|
|
',"'. db_es($field->getName()) .'",'. db_ei($field->getDataType()) . |
455
|
|
|
',"'. db_es($field->getDisplayType()) .'","'. db_es($field->getDisplaySize()) .'","'. db_es($field->getLabel()) . |
456
|
|
|
'","'. db_es($field->getDescription()) .'","'. db_es($field->getScope()) .'",'. db_ei($field->getRequired()) . |
457
|
|
|
','. db_ei($field->getEmptyOk()) .','. db_ei($field->getKeepHistory()) .','. db_ei($field->getSpecial()) . |
458
|
|
|
',"'. db_es(implode(",",$dest_val_func)) .'","'. db_es($field->getDefaultValue(true)) .'")'; |
459
|
|
|
|
460
|
|
|
$res_insert = db_query($sql_insert); |
461
|
|
|
//echo $sql_insert; |
462
|
|
|
if (!$res_insert || db_affected_rows($res_insert) <= 0) { |
463
|
|
|
$this->setError($Language->getText('tracker_common_field_factory','ins_err',array($field_array["field_id"],$atid_dest,db_error()))); |
|
|
|
|
464
|
|
|
return false; |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
|
468
|
|
|
// |
469
|
|
|
// Copy artifact_field_usage records |
470
|
|
|
// |
471
|
|
|
$place = ($field->getPlace() == ""?"null":$field->getPlace()); |
472
|
|
|
$sql_insert = 'INSERT INTO artifact_field_usage VALUES ('.$field->getID().','.$atid_dest.','.$field->getUseIt(). |
473
|
|
|
','.$place.')'; |
474
|
|
|
|
475
|
|
|
//echo $sql_insert; |
476
|
|
|
$res_insert = db_query($sql_insert); |
477
|
|
|
if (!$res_insert || db_affected_rows($res_insert) <= 0) { |
478
|
|
|
$this->setError($Language->getText('tracker_common_field_factory','use_ins_err',array($field->getID(),$atid_dest,db_error()))); |
479
|
|
|
return false; |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
} // while |
483
|
|
|
|
484
|
|
|
|
485
|
|
|
|
486
|
|
|
// |
487
|
|
|
// Copy artifact_field_value_list records |
488
|
|
|
// |
489
|
|
|
$sql='SELECT field_id,value_id,value,description,order_id,status '. |
490
|
|
|
'FROM artifact_field_value_list '. |
491
|
|
|
'WHERE group_artifact_id='. db_ei($this->ArtifactType->getID()) ; |
492
|
|
|
|
493
|
|
|
//echo $sql; |
494
|
|
|
|
495
|
|
|
$res = db_query($sql); |
496
|
|
|
|
497
|
|
|
while ($field_array = db_fetch_array($res)) { |
498
|
|
|
$sql_insert = 'INSERT INTO artifact_field_value_list VALUES ('. db_ei($field_array["field_id"]) .','. db_ei($atid_dest) .','. db_ei($field_array["value_id"]) . |
499
|
|
|
',"'. db_es($field_array["value"]) .'","'. db_es($field_array["description"]) .'",'. db_ei($field_array["order_id"]) . |
500
|
|
|
',"'. db_es($field_array["status"]) .'")'; |
501
|
|
|
|
502
|
|
|
//echo $sql_insert; |
503
|
|
|
$res_insert = db_query($sql_insert); |
504
|
|
|
if (!$res_insert || db_affected_rows($res_insert) <= 0) { |
505
|
|
|
$this->setError($Language->getText('tracker_common_field_factory','vl_ins_err',array($field_array["field_id"],$atid_dest,db_error()))); |
506
|
|
|
return false; |
507
|
|
|
} |
508
|
|
|
} // while |
509
|
|
|
|
510
|
|
|
return true; |
511
|
|
|
|
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
|
515
|
|
|
/** |
516
|
|
|
* |
517
|
|
|
* Delete all the fields informations for a tracker |
518
|
|
|
* |
519
|
|
|
* @param atid: the tracker id |
520
|
|
|
* |
521
|
|
|
* @return boolean |
522
|
|
|
*/ |
523
|
|
|
function deleteFields($atid) { |
524
|
|
|
|
525
|
|
|
// |
526
|
|
|
// Remove fields permissions |
527
|
|
|
// |
528
|
|
|
foreach($this->USAGE_BY_ID as $field_id => $field) { |
529
|
|
|
permission_clear_all_fields_tracker($this->ArtifactType->getGroupID(), $atid, $field_id); |
530
|
|
|
} |
531
|
|
|
|
532
|
|
|
// |
533
|
|
|
// Delete artifact_field records |
534
|
|
|
// |
535
|
|
|
$sql='DELETE '. |
536
|
|
|
'FROM artifact_field '. |
537
|
|
|
'WHERE group_artifact_id='. db_ei($atid) ; |
538
|
|
|
|
539
|
|
|
//echo $sql; |
540
|
|
|
|
541
|
|
|
$res = db_query($sql); |
542
|
|
|
|
543
|
|
|
// |
544
|
|
|
// Delete artifact_field_usage records |
545
|
|
|
// |
546
|
|
|
$sql='DELETE '. |
547
|
|
|
'FROM artifact_field_usage '. |
548
|
|
|
'WHERE group_artifact_id='. db_ei($atid) ; |
549
|
|
|
|
550
|
|
|
//echo $sql; |
551
|
|
|
|
552
|
|
|
$res = db_query($sql); |
553
|
|
|
|
554
|
|
|
// |
555
|
|
|
// Delete artifact_field_value_list records |
556
|
|
|
// |
557
|
|
|
$sql='DELETE '. |
558
|
|
|
'FROM artifact_field_value_list '. |
559
|
|
|
'WHERE group_artifact_id='. db_ei($atid) ; |
560
|
|
|
|
561
|
|
|
//echo $sql; |
562
|
|
|
|
563
|
|
|
$res = db_query($sql); |
564
|
|
|
|
565
|
|
|
return true; |
566
|
|
|
|
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
/** |
570
|
|
|
* Check if a field id already exist for an artifact type |
571
|
|
|
* |
572
|
|
|
* @param field_id: the field id |
573
|
|
|
* |
574
|
|
|
* @return boolean - exist or not |
575
|
|
|
*/ |
576
|
|
|
function existFieldId($field_id) { |
577
|
|
|
$sql = "SELECT * FROM artifact_field WHERE group_artifact_id=". db_ei($this->ArtifactType->getID()) . |
578
|
|
|
" AND field_id=". db_ei($field_id) ; |
579
|
|
|
|
580
|
|
|
$result = db_query($sql); |
581
|
|
|
if ($result && db_numrows($result) > 0) { |
582
|
|
|
return true; |
583
|
|
|
} else { |
584
|
|
|
return false; |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
/** |
590
|
|
|
* Compute the default value given a data type and a display type |
591
|
|
|
* |
592
|
|
|
* @param data_type: the field data type (string, int, flat or date) |
593
|
|
|
* @param display_size: the field display size |
594
|
|
|
* |
595
|
|
|
* @return string |
596
|
|
|
*/ |
597
|
|
|
function getDefaultValue($data_type,$display_type) { |
598
|
|
|
|
599
|
|
|
$af = new ArtifactField(); |
600
|
|
|
|
601
|
|
|
if ( ($data_type == $af->DATATYPE_INT || $data_type == $af->DATATYPE_USER) |
602
|
|
|
&&($display_type == "SB") ) |
603
|
|
|
return "100"; |
604
|
|
|
|
605
|
|
|
if ( ($data_type == $af->DATATYPE_INT || $data_type == $af->DATATYPE_USER) |
606
|
|
|
&&($display_type == "MB") ) |
607
|
|
|
return "100"; |
608
|
|
|
|
609
|
|
|
if ( ($data_type == $af->DATATYPE_TEXT) |
610
|
|
|
&&($display_type == "TF") ) |
611
|
|
|
return ""; |
612
|
|
|
|
613
|
|
|
if ( ($data_type == $af->DATATYPE_TEXT) |
614
|
|
|
&&($display_type == "TA") ) |
615
|
|
|
return ""; |
616
|
|
|
|
617
|
|
|
if ( ($data_type == $af->DATATYPE_DATE) |
618
|
|
|
&&($display_type == "DF") ) |
619
|
|
|
return ""; |
620
|
|
|
|
621
|
|
|
if ( ($data_type == $af->DATATYPE_FLOAT) |
622
|
|
|
&&($display_type == "TF") ) |
623
|
|
|
return "0.0"; |
624
|
|
|
|
625
|
|
|
if ( ($data_type == $af->DATATYPE_INT) |
626
|
|
|
&&($display_type == "TF") ) |
627
|
|
|
return "0"; |
628
|
|
|
|
629
|
|
|
return ""; |
630
|
|
|
|
631
|
|
|
} |
632
|
|
|
|
633
|
|
|
/** |
634
|
|
|
* Create a new field |
635
|
|
|
* |
636
|
|
|
* @param description: the field description |
637
|
|
|
* @param label: the field label |
638
|
|
|
* @param data_type: the field data type (string, int, flat or date) |
639
|
|
|
* @param display_type: the field display type (select box, text field, ...) |
640
|
|
|
* @param display_size: the field display size |
641
|
|
|
* @param rank_on_screen: rank on screen |
642
|
|
|
* @param empty_ok: allow empty fill |
643
|
|
|
* @param keep_history: keep in the history |
644
|
|
|
* @param special: is the field has special process |
645
|
|
|
* @param use_it: this field is used or not |
646
|
|
|
* @param field_set_id: the field set id that this field belong to |
647
|
|
|
* |
648
|
|
|
* @return boolean - succeed or failed |
649
|
|
|
*/ |
650
|
|
|
function createField($description,$label,$data_type,$display_type, |
651
|
|
|
$display_size,$rank_on_screen, |
652
|
|
|
$empty_ok,$keep_history,$special,$use_it,$field_set_id) { |
653
|
|
|
|
654
|
|
|
global $Language; |
655
|
|
|
|
656
|
|
|
// Check arguments |
657
|
|
|
if ( $data_type=="" || $display_type=="" || $label=="" ) { |
658
|
|
|
$this->setError($Language->getText('tracker_common_field_factory','label_requ')); |
659
|
|
|
return false; |
660
|
|
|
} |
661
|
|
|
|
662
|
|
|
$field_id = $this->ArtifactType->getNextFieldID(); |
663
|
|
|
$field_name = $this->ArtifactType->buildFieldName($this->ArtifactType->getNextFieldID()); |
664
|
|
|
|
665
|
|
|
$af = new ArtifactField($this->ArtifactType->getID(),""); |
666
|
|
|
|
667
|
|
|
// Default values |
668
|
|
|
$empty_ok = ($empty_ok?$empty_ok:0); |
669
|
|
|
$keep_history = ($keep_history?$keep_history:0); |
670
|
|
|
$use_it = ($use_it?$use_it:0); |
671
|
|
|
$special = ($special?$special:0); |
672
|
|
|
$display_size = (($display_size != "N/A") ? $display_size : "" ); |
673
|
|
|
|
674
|
|
|
$default_value = $this->getDefaultValue($data_type,$display_type); |
675
|
|
|
// First create the artifact_field |
676
|
|
|
$sql = "INSERT INTO artifact_field VALUES (". |
677
|
|
|
db_ei($field_id) .",". db_ei($this->ArtifactType->getID()) .",". db_ei($field_set_id) .",'". db_es($field_name) ."',". db_ei($data_type) .",'". db_es($display_type) ."','". db_es($display_size) ."','". |
678
|
|
|
db_es($label) ."','". db_es($description) ."','',0,". db_ei($empty_ok) .",". db_ei($keep_history) .",". db_ei($special) .",'','". db_es($default_value) ."')"; |
679
|
|
|
|
680
|
|
|
$res_insert = db_query($sql); |
681
|
|
|
if (!$res_insert || db_affected_rows($res_insert) <= 0) { |
682
|
|
|
$this->setError($Language->getText('tracker_common_field_factory','ins_err',array($field_id,$this->ArtifactType->getID(),db_error()))); |
683
|
|
|
return false; |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
// Then, insert the artifact_field_usage |
687
|
|
|
$sql = "INSERT INTO artifact_field_usage VALUES (". |
688
|
|
|
db_ei($field_id) .",". db_ei($this->ArtifactType->getID()) .",". db_ei($use_it) .",'". |
689
|
|
|
db_ei($rank_on_screen) ."')"; |
690
|
|
|
|
691
|
|
|
$res_insert = db_query($sql); |
692
|
|
|
if (!$res_insert || db_affected_rows($res_insert) <= 0) { |
693
|
|
|
$this->setError($Language->getText('tracker_common_field_factory','use_ins_err',array($field_id,$this->ArtifactType->getID(),db_error()))); |
694
|
|
|
return false; |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
// We need to insert with the default value, records in artifact_field_value table |
698
|
|
|
// for the new field |
699
|
|
|
$sql_artifacts='SELECT artifact_id '. |
700
|
|
|
'FROM artifact '. |
701
|
|
|
'WHERE group_artifact_id='. db_ei($this->ArtifactType->getID()) ; |
702
|
|
|
|
703
|
|
|
//echo $sql_artifacts; |
704
|
|
|
|
705
|
|
|
$res = db_query($sql_artifacts); |
706
|
|
|
|
707
|
|
|
|
708
|
|
|
// Insert artifact_field_value record |
709
|
|
|
$name = ''; |
710
|
|
|
switch ( $data_type ) { |
711
|
|
|
case $af->DATATYPE_TEXT: |
712
|
|
|
$name = "valueText"; |
713
|
|
|
break; |
714
|
|
|
|
715
|
|
|
case $af->DATATYPE_INT: |
716
|
|
|
case $af->DATATYPE_USER: |
717
|
|
|
$name = "valueInt"; |
718
|
|
|
break; |
719
|
|
|
|
720
|
|
|
case $af->DATATYPE_FLOAT: |
721
|
|
|
$name = "valueFloat"; |
722
|
|
|
break; |
723
|
|
|
|
724
|
|
|
case $af->DATATYPE_DATE: |
725
|
|
|
$name = "valueDate"; |
726
|
|
|
break; |
727
|
|
|
} // switch |
728
|
|
|
|
729
|
|
|
$sql = "INSERT INTO artifact_field_value (field_id,artifact_id,$name) VALUES "; |
730
|
|
|
|
731
|
|
|
$count = db_numrows($res); |
732
|
|
|
for ($i=0; $i<$count; $i++) { |
733
|
|
|
$id = db_result($res,$i,"artifact_id"); |
734
|
|
|
if ($i > 0) $sql .= ","; |
735
|
|
|
$sql .= "(". db_ei($field_id) .",". db_ei($id) .",'". db_es($default_value) ."')"; |
736
|
|
|
} |
737
|
|
|
|
738
|
|
|
$result=db_query($sql); |
739
|
|
|
|
740
|
|
|
|
741
|
|
|
// If select box or multi select box, we need to create the None value |
742
|
|
|
if ( $display_type == "SB" || $display_type == "MB" ) { |
743
|
|
|
$sql = "INSERT INTO artifact_field_value_list VALUES ( ". db_ei($field_id) .",". db_ei($this->ArtifactType->getID()) . |
744
|
|
|
",100,'". db_es($Language->getText('global','none')) ."','',10,'P')"; |
745
|
|
|
$result=db_query($sql); |
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
// Reload the fields |
749
|
|
|
$this->fetchData($this->ArtifactType->getID()); |
750
|
|
|
|
751
|
|
|
//Set permissions |
752
|
|
|
$permissions = array($field_id => |
753
|
|
|
array( |
754
|
|
|
$GLOBALS['UGROUP_ANONYMOUS'] => permission_get_input_value_from_permission('TRACKER_FIELD_READ'), |
755
|
|
|
$GLOBALS['UGROUP_REGISTERED'] => permission_get_input_value_from_permission('TRACKER_FIELD_SUBMIT'), |
756
|
|
|
$GLOBALS['UGROUP_PROJECT_MEMBERS'] => permission_get_input_value_from_permission('TRACKER_FIELD_UPDATE') |
757
|
|
|
) |
758
|
|
|
); |
759
|
|
|
|
760
|
|
|
permission_process_update_fields_permissions($this->ArtifactType->getGroupID(), |
761
|
|
|
$this->ArtifactType->getID(), |
762
|
|
|
$this->getAllUsedFields(), |
763
|
|
|
$permissions |
764
|
|
|
); |
765
|
|
|
return true; |
766
|
|
|
|
767
|
|
|
} |
768
|
|
|
|
769
|
|
|
|
770
|
|
|
} |
771
|
|
|
|
772
|
|
|
?> |
773
|
|
|
|
This checks looks for assignemnts to variables using the
list(...)
function, where not all assigned variables are subsequently used.Consider the following code example.
Only the variables
$a
and$c
are used. There was no need to assign$b
.Instead, the list call could have been.