GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ArtifactFieldFactory::createField()   F
last analyzed

Complexity

Conditions 22
Paths 1217

Size

Total Lines 118
Code Lines 71

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 118
rs 2
cc 22
eloc 71
nc 1217
nop 11

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $val is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
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)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $val is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
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
0 ignored issues
show
Documentation introduced by
The doc-type array{ArtifactField} could not be parsed: Unknown type name "array{ArtifactField}" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
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) ) {
0 ignored issues
show
Unused Code introduced by
The assignment to $key is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
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)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
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())));
0 ignored issues
show
Bug introduced by
The variable $field_array seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
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