00001 <?php
00002 # This file is part of the Savane project
00003 # <http://gna.org/projects/savane/>
00004 #
00005 # $Id: data.php 5387 2006-02-15 15:21:25Z yeupou $
00006 #
00007 # Copyright 1999-2000 (c) The SourceForge Crew
00008 # Copyright 2001-2002 (c) Laurent Julliard, CodeX Team, Xerox
00009 #
00010 # Copyright 2003-2005 (c) Mathieu Roy <yeupou--gnu.org>
00011 # Yves Perrin <yves.perrin--cern.ch>
00012 #
00013 #
00014 # The Savane project is free software; you can redistribute it and/or
00015 # modify it under the terms of the GNU General Public License
00016 # as published by the Free Software Foundation; either version 2
00017 # of the License, or (at your option) any later version.
00018 #
00019 # The Savane project is distributed in the hope that it will be useful,
00020 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00022 # GNU General Public License for more details.
00023 #
00024 # You should have received a copy of the GNU General Public License
00025 # along with the Savane project; if not, write to the Free Software
00026 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 function trackers_data_get_all_fields ($group_id=false,$reload=false)
00038 {
00039
00040
00041
00042
00043
00044
00045
00046
00047 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME, $AT_START;
00048
00049 # Do nothing if already set and reload not forced
00050 if (isset($BF_USAGE_BY_ID) && !$reload)
00051 {
00052 return;
00053 }
00054
00055 # Clean up the array
00056 $BF_USAGE_BY_ID=array();
00057 $BF_USAGE_BY_NAME=array();
00058
00059 # First get the all the defaults.
00060 $sql='SELECT '.ARTIFACT.'_field.bug_field_id, field_name, display_type, '.
00061 'display_size,label, description,scope,required,empty_ok,keep_history,special, custom, '.
00062 'group_id, use_it,show_on_add,show_on_add_members, place, custom_label,'.
00063 'custom_description,custom_display_size,custom_empty_ok,custom_keep_history '.
00064 'FROM '.ARTIFACT.'_field, '.ARTIFACT.'_field_usage '.
00065 'WHERE group_id=100 '.
00066 'AND '.ARTIFACT.'_field.bug_field_id='.ARTIFACT.'_field_usage.bug_field_id ';
00067
00068 $res_defaults = db_query($sql);
00069
00070 # Now put all used fields in a global array for faster access
00071 # Index both by field_name and bug_field_id
00072 while ($field_array = db_fetch_array($res_defaults))
00073 {
00074 $BF_USAGE_BY_ID[$field_array['bug_field_id'] ] = $field_array;
00075 $BF_USAGE_BY_NAME[$field_array['field_name'] ] = $field_array;
00076 }
00077
00078 # Then select all project specific entries
00079 $sql='SELECT '.ARTIFACT.'_field.bug_field_id, field_name, display_type, '.
00080 'display_size,label, description,scope,required,empty_ok,keep_history,special, custom, '.
00081 'group_id, use_it, show_on_add, show_on_add_members, place, custom_label,'.
00082 'custom_description,custom_display_size,custom_empty_ok,custom_keep_history '.
00083 'FROM '.ARTIFACT.'_field, '.ARTIFACT.'_field_usage '.
00084 'WHERE group_id='.$group_id.
00085 ' AND '.ARTIFACT.'_field.bug_field_id= '.ARTIFACT.'_field_usage.bug_field_id ';
00086
00087
00088 $res_project = db_query($sql);
00089
00090 # And override entries in the default array
00091 while ($field_array = db_fetch_array($res_project))
00092 {
00093 $BF_USAGE_BY_ID[$field_array['bug_field_id'] ] = $field_array;
00094 $BF_USAGE_BY_NAME[$field_array['field_name'] ] = $field_array;
00095 }
00096
00097 #Debug code
00098 #print "<br />DBG - At end of bug_get_all_fields: $rows";
00099 #reset($BF_USAGE_BY_NAME);
00100 #while (list($key, $val) = each($BF_USAGE_BY_NAME))
00101 #{
00102 #print "<br />DBG - $key -> use_it: $val[use_it], $val[place]";
00103 #}
00104
00105 # rewind internal pointer of global arrays
00106 reset($BF_USAGE_BY_ID);
00107 reset($BF_USAGE_BY_NAME);
00108 $AT_START = true;
00109 }
00110
00111
00112 function trackers_data_get_item_group($item_id)
00113 {
00114 return db_result(
00115 db_query("SELECT group_id FROM ".ARTIFACT." WHERE bug_id='$item_id'"),
00116 0,
00117 'group_id');
00118 }
00119
00120 function &trackers_data_get_notification_settings($group_id, $tracker_name)
00121 {
00122 $result = db_query("SELECT * FROM groups WHERE group_id=$group_id");
00123 if (db_numrows($result) < 1)
00124 {
00125 exit_no_group();
00126 }
00127
00128 $settings = array();
00129
00130 $settings['glnotif'] = db_result($result,0,$tracker_name."_glnotif");
00131 $settings['glsendall'] = db_result($result,0,"send_all_".$tracker_name);
00132 $settings['glnewad'] = db_result($result,0,"new_".$tracker_name."_address");
00133 $settings['private_exclude'] = db_result($result,0,$tracker_name."_private_exclude_address");
00134
00135 $cat_field_name = "category_id";
00136 # Warning: The hardcoded fiels names: bug_fv_id and bug_field_id will need to be changed
00137 # one day to generic names since they apply to bugs but also to suuports,tasks,
00138 # and patch related tables. For now these fileds are called bug_xxx whatever
00139 # the service related tables. Too much work to make all the changes in the code.
00140 $sql="SELECT ".$tracker_name."_field_value.bug_fv_id,".$tracker_name."_field_value.value,".$tracker_name."_field_value.email_ad,".$tracker_name."_field_value.send_all_flag ".
00141 "FROM ".$tracker_name."_field, ".$tracker_name."_field_value ".
00142 "WHERE ".$tracker_name."_field_value.group_id='$group_id' ".
00143 "AND ".$tracker_name."_field.field_name='$cat_field_name' ".
00144 "AND ".$tracker_name."_field_value.bug_field_id=".$tracker_name."_field.bug_field_id ".
00145 "AND ".$tracker_name."_field_value.status!='H'";
00146
00147 $result=db_query($sql);
00148 $settings['nb_categories']=db_numrows($result);
00149 $settings['category'] = array();
00150 for ($i=0; $i < $settings['nb_categories'] ; $i++) {
00151
00152 $settings['category'][$i] = array();
00153 $settings['category'][$i]['name'] = db_result($result, $i, 'value');
00154 $settings['category'][$i]['fv_id'] = db_result($result, $i, 'bug_fv_id');
00155 $email = db_result($result, $i, 'email_ad');
00156 if ($email == '100')
00157 { $email = ""; }
00158 $settings['category'][$i]['email'] = $email;
00159 $settings['category'][$i]['send_all_flag'] = db_result($result, $i, 'send_all_flag');
00160 }
00161 return $settings;
00162 }
00163
00164 function trackers_data_show_notification_settings($group_id, $tracker_name, $show_intro_msg)
00165 {
00166 $grtrsettings = &trackers_data_get_notification_settings($group_id, $tracker_name);
00167
00168 if (user_ismember($group_id,'A'))
00169 {
00170 if ($grtrsettings['glnotif'] == 0) {
00171 $categoryradio = "CHECKED";
00172 $globalradio = "";
00173 $bothradio = "";
00174 }
00175 if ($grtrsettings['glnotif'] == 1) {
00176 $categoryradio = "";
00177 $globalradio = "CHECKED";
00178 $bothradio = "";
00179 }
00180 if ($grtrsettings['glnotif'] == 2) {
00181 $categoryradio = "";
00182 $globalradio = "";
00183 $bothradio = "CHECKED";
00184 }
00185 if ($grtrsettings['nb_categories'] > 0) {
00186 if ($show_intro_msg != 0) {
00187 print '<p>'.sprintf(_("As a project administrator you must decide if the list of persons to be systematically notified on new %s submissions (and possibly updates) depend on the categories or not and you must provide the corresponding email addresses (comma separated list)."), $tracker_name).'</p>';
00188
00189 }
00190 print '
00191 <INPUT TYPE="RADIO" NAME="'.$tracker_name.'_notif_scope" VALUE="global" '.$globalradio.' /> <span class="preinput">'._("Notify persons in the global list only").'</span><br />
00192 <INPUT TYPE="RADIO" NAME="'.$tracker_name.'_notif_scope" VALUE="category" '.$categoryradio.' /> <span class="preinput">'._("Notify persons in the category related list instead of the global list").'</span><br />
00193 <INPUT TYPE="RADIO" NAME="'.$tracker_name.'_notif_scope" VALUE="both" '.$bothradio.' /> <span class="preinput">'._("Notify persons in the category related list in addition to the global list").'</span><br />
00194
00195
00196 <h4>'._("Category related lists").'</h4>';
00197 print '<INPUT TYPE="HIDDEN" NAME="'.$tracker_name.'_nb_categories" VALUE="'.$grtrsettings['nb_categories'].'" />';
00198
00199 for ($i=0; $i < $grtrsettings['nb_categories'] ; $i++)
00200 {
00201 print '<INPUT TYPE="HIDDEN" NAME="'.$tracker_name.'_cat_'.$i.'_bug_fv_id" VALUE="'.$grtrsettings['category'][$i]['fv_id'].'" />';
00202 print '<span class="preinput">'.$grtrsettings['category'][$i]['name'].'</span><br /> <INPUT TYPE="TEXT" NAME="'.$tracker_name.'_cat_'.$i.'_email" VALUE="'.$grtrsettings['category'][$i]['email'].'" SIZE="50" MAXLENGTH="255" />
00203 <span class="preinput">(
00204 <INPUT TYPE="CHECKBOX" NAME="'.$tracker_name.'_cat_'.$i.'_send_all_flag" VALUE="1" '. (($grtrsettings['category'][$i]['send_all_flag'])?'checked="checked"':'') .' />'._("Send on all updates").')</span><br />
00205 ';
00206 }
00207
00208 print '<h4>'._("Global list").'</h4>';
00209
00210 } else {
00211 if ($show_intro_msg != 0) {
00212 print '<p>'.sprintf(_("As a project administrator you must decide if the list of persons to be systematically notified on new %s submissions (and possibly updates) depend on the categories or not and you must provide the corresponding email addresses (comma separated list)."), $tracker_name).'</p>';
00213 }
00214 }
00215 print '<span class="preinput">'._("Global List:").'</span><br /> <INPUT TYPE="TEXT" NAME="'.$tracker_name.'_new_item_address" VALUE="'.$grtrsettings['glnewad'].'" SIZE="50" MAXLENGTH="255" />
00216 <span class="preinput">(<INPUT TYPE="CHECKBOX" NAME="'.$tracker_name.'_send_all_changes" VALUE="1" '. (($grtrsettings['glsendall'])?'CHECKED':'') .'>'._("Send on all updates").')</span>';
00217
00218 print '<h4>'._("Private items exclude list").'</h4>';
00219 if ($show_intro_msg != 0) {
00220 print '<p>'._("Addresses registered in this list will be excluded from default mail notification for private items.").'</p>';
00221 }
00222
00223 print '<span class="preinput">'._("Exclude List:").'</span><br /> <INPUT TYPE="TEXT" NAME="'.$tracker_name.'_private_exclude_address" VALUE="'.$grtrsettings['private_exclude'].'" SIZE="50" MAXLENGTH="255" /><br />';
00224
00225 }
00226 }
00227
00228 function trackers_data_post_notification_settings($group_id, $tracker_name)
00229 {
00230
00231 global $feedback;
00232
00233 $local_feedback = "";
00234 # build the variable names related to elements always present in the form
00235 # and get their values
00236
00237 $notif_scope_name = $tracker_name."_notif_scope";
00238 $notif_scope = $GLOBALS[$notif_scope_name];
00239 $new_item_address_name = $tracker_name."_new_item_address";
00240 $new_item_address = $GLOBALS[$new_item_address_name];
00241 $send_all_changes_name = $tracker_name."_send_all_changes";
00242 $send_all_changes = $GLOBALS[$send_all_changes_name];
00243 $nb_categories_name = $tracker_name."_nb_categories";
00244 $nb_categories = $GLOBALS[$nb_categories_name];
00245 $private_exclude_address_name = $tracker_name."_private_exclude_address";
00246 $private_exclude_address = $GLOBALS[$private_exclude_address_name];
00247
00248 if ($notif_scope != "global") {
00249 if ($notif_scope == "category") {
00250 $notif_value = 0;
00251 }
00252 if ($notif_scope == "both") {
00253 $notif_value = 2;
00254 }
00255 } else {
00256 $notif_value = 1;
00257 }
00258
00259 # set global notification info for this group
00260 $res_gl=db_query("UPDATE groups SET "
00261 .$tracker_name."_glnotif='$notif_value', "
00262 ."send_all_".$tracker_name."='$send_all_changes', "
00263 ."new_".$tracker_name."_address=".($new_item_address? "'$new_item_address' " : "''").", "
00264 .$private_exclude_address_name.'='.($private_exclude_address? "'$private_exclude_address' " : "''")
00265 . " WHERE group_id=$group_id");
00266 if (!$res_gl)
00267 { $local_feedback .= _("groups table Update failed.").' '.db_error(); }
00268
00269 $ok = 0;
00270 if ($nb_categories > 0) {
00271 for ($i=0; $i<$nb_categories; $i++) {
00272 $current_fv_name = $tracker_name."_cat_".$i."_bug_fv_id";
00273 $current_fv_id = $GLOBALS[$current_fv_name];
00274 $current_email_name = $tracker_name."_cat_".$i."_email";
00275 $current_email = $GLOBALS[$current_email_name];
00276 # if ($current_email && !validate_email($current_email))
00277 # {
00278 # $local_feedback .= _("[".$tracker_name."] notification address: ".$current_email." appeared Invalid");
00279 # $current_email='';
00280 # }
00281 $current_send_all_name = $tracker_name."_cat_".$i."_send_all_flag";
00282 $current_send_all_flag = $GLOBALS[$current_send_all_name];
00283
00284 $res_cat=db_query("UPDATE ".$tracker_name."_field_value SET "
00285 ."email_ad='$current_email', "
00286 ."send_all_flag='$current_send_all_flag' "
00287 ." WHERE bug_fv_id=$current_fv_id");
00288 if ($res_cat) {
00289 $ok++;
00290 } else {
00291 $local_feedback .= _($tracker_name."_field_value table Update failed.").' '.db_error();
00292 }
00293 }
00294 }
00295 if (($res_gl) && ($ok == $nb_categories) && ($local_feedback == "")) {
00296 return 1;
00297 } else {
00298 if ($local_feedback != "") { fb($local_feedback); }
00299 return 0;
00300 }
00301 }
00302
00303 function trackers_data_get_item_notification_info($item_id, $artifact, $updated)
00304 {
00305 $emailad = "";
00306 $sendemail = 0;
00307 # Get group information bur new entity notification settings
00308 $sql="SELECT groups.$artifact"."_glnotif, groups.send_all_"."$artifact, groups.new_"."$artifact"."_address ".
00309 "FROM "."$artifact, groups ".
00310 "WHERE "."$artifact.bug_id='$item_id' ".
00311 "AND groups.group_id="."$artifact.group_id";
00312 $result=db_query($sql);
00313
00314 $glnotif = db_result($result,0,$artifact."_glnotif");
00315 $glsendall = db_result($result,0,"send_all_".$artifact);
00316 $glnewad = db_result($result,0,"new_".$artifact."_address");
00317 if ($glnotif != 1) { # if not 'global only'
00318 $cat_field_name = "category_id";
00319
00320 $sql="SELECT "."$artifact"."_field_value.email_ad, "."$artifact"."_field_value.send_all_flag ".
00321 "FROM "."$artifact"."_field_value, "."$artifact"."_field, $artifact ".
00322 "WHERE "."$artifact.bug_id='$item_id' ".
00323 "AND "."$artifact"."_field.field_name='$cat_field_name' ".
00324 "AND "."$artifact"."_field_value.bug_field_id="."$artifact"."_field.bug_field_id ".
00325 "AND "."$artifact"."_field_value.group_id="."$artifact.group_id ".
00326 "AND "."$artifact"."_field_value.value_id="."$artifact.category_id";
00327
00328 $result=db_query($sql);
00329 $rows=db_numrows($result);
00330 if ($rows > 0) {
00331 $sendallflag = db_result($result, 0, 'send_all_flag');
00332 if (($updated == 0) || (($updated == 1) && ($sendallflag == 1))) {
00333 $emailad .= db_result($result, 0, 'email_ad');
00334 }
00335 } else {
00336 # could be that administrator closes category notification and forgot
00337 # to define categories BUT in most cases it means the submitter selected
00338 # the 'NONE' category for this bug
00339 if (($updated == 0) || (($updated == 1) && ($glsendall == 1))) {
00340 $emailad .= $glnewad;
00341 }
00342 }
00343 }
00344 if ($glnotif > 0) { # if not 'category only'
00345 if (($updated == 0) || (($updated == 1) && ($glsendall == 1))) {
00346 if ($emailad != "") {
00347 $emailad .= ',';
00348 }
00349 $emailad .= $glnewad;
00350 }
00351 }
00352 if (trim($emailad) != "") {
00353 $sendemail = 1;
00354 }
00355 # print "EMAILAD=$emailad SENDEMAIL=$sendemail";
00356 return array($emailad, $sendemail);
00357 }
00358
00359
00360 function cmp_place($ar1, $ar2)
00361 {
00362 if ($ar1['place']< $ar2['place'])
00363 return -1;
00364 else if ($ar1['place']>$ar2['place'])
00365 return 1;
00366 return 0;
00367 }
00368
00369 function cmp_place_query($ar1, $ar2)
00370 {
00371 if ($ar1['place_query']< $ar2['place_query'])
00372 return -1;
00373 else if ($ar1['place_query']>$ar2['place_query'])
00374 return 1;
00375 return 0;
00376 }
00377
00378 function cmp_place_result($ar1, $ar2)
00379 {
00380 if ($ar1['place_result']< $ar2['place_result'])
00381 return -1;
00382 else if ($ar1['place_result']>$ar2['place_result'])
00383 return 1;
00384 return 0;
00385 }
00386
00387 function trackers_data_get_all_report_fields($group_id=false,$report_id=100)
00388 {
00389 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00390
00391
00392
00393
00394
00395
00396 # Build the list of fields involved in this report
00397 $sql = "SELECT * FROM ".ARTIFACT."_report_field WHERE report_id='".safeinput($report_id)."'";
00398 $res = db_query($sql);
00399
00400 while ($arr = db_fetch_array($res))
00401 {
00402 $field = $arr['field_name'];
00403 $field_id = trackers_data_get_field_id($field);
00404 $BF_USAGE_BY_NAME[$field]['show_on_query'] =
00405 $BF_USAGE_BY_ID[$field_id]['show_on_query'] = $arr['show_on_query'];
00406
00407 $BF_USAGE_BY_NAME[$field]['show_on_result'] =
00408 $BF_USAGE_BY_ID[$field_id]['show_on_result'] = $arr['show_on_result'];
00409
00410 $BF_USAGE_BY_NAME[$field]['place_query'] =
00411 $BF_USAGE_BY_ID[$field_id]['place_query'] = $arr['place_query'];
00412
00413 $BF_USAGE_BY_NAME[$field]['place_result'] =
00414 $BF_USAGE_BY_ID[$field_id]['place_result'] = $arr['place_result'];
00415
00416 $BF_USAGE_BY_NAME[$field]['col_width'] =
00417 $BF_USAGE_BY_ID[$field_id]['col_width'] = $arr['col_width'];
00418 }
00419 }
00420
00421 function trackers_data_get_field_predefined_values ($field, $group_id=false, $checked=false,$by_field_id=false,$active_only=true)
00422 {
00423
00424
00425
00426
00427
00428
00429 $field_id = ($by_field_id ? $field : trackers_data_get_field_id($field));
00430 $field_name = ($by_field_id ? trackers_data_get_field_name($field) : $field);
00431
00432 # The "Assigned_to" box requires some special processing
00433 # because possible values are project members) and they are
00434 # not stored in the trackers_field_value table but in the user_group table
00435 if ($field_name == 'assigned_to')
00436 {
00437 $res_value = trackers_data_get_technicians($group_id);
00438 }
00439 else if ($field_name == 'submitted_by')
00440 {
00441 $res_value = trackers_data_get_submitters($group_id);
00442 }
00443 else
00444 {
00445
00446 # If only active field
00447 if ($active_only)
00448 {
00449 if ($checked)
00450 {
00451 $status_cond = "AND (status IN ('A','P') OR value_id='$checked') ";
00452 }
00453 else
00454 {
00455 $status_cond = "AND status IN ('A','P') ";
00456 }
00457 }
00458
00459 # CAUTION !! the fields value_id and value must be first in the
00460 # select statement because the output is used in the html_build_select_box
00461 # function
00462
00463 # yeupou@gnu.org 2003-11-24
00464 # FIXME!!!!! WHAT IS THIS CRAP!
00465 # It _on purpose_ ignores the permanent values for the
00466 # system when a group have his own values.
00467 # And when creating group specific values, it insert the permanent
00468 # system values in the group specific values.
00469 #
00470 # Can someone bring a reasonnable explanation for such a behavior?
00471 # - permanent field must by nature be permanent, in any case!
00472 # - database must never duplicates information without good reason
00473 #
00474 # When improving this code, please change that so it uses the permanent
00475 # values in any case, whatever the group specific values may be.
00476
00477 # Look for project specific values first
00478 $sql="SELECT value_id,value,bug_fv_id,bug_field_id,group_id,description,order_id,status ".
00479 "FROM ".ARTIFACT."_field_value ".
00480 "WHERE group_id=$group_id AND bug_field_id=$field_id ".
00481 $status_cond." ORDER BY order_id,value ASC";
00482 $res_value = db_query($sql);
00483 $rows=db_numrows($res_value);
00484
00485 # If no specific value for this group then look for default values
00486 if ($rows == 0)
00487 {
00488 $sql="SELECT value_id,value,bug_fv_id,bug_field_id,group_id,description,order_id,status ".
00489 "FROM ".ARTIFACT."_field_value ".
00490 "WHERE group_id=100 AND bug_field_id=$field_id ".
00491 $status_cond." ORDER BY order_id,value ASC";
00492 $res_value = db_query($sql);
00493 $rows=db_numrows($res_value);
00494 }
00495 }
00496
00497 return($res_value);
00498
00499 }
00500
00501 function trackers_data_use_field_predefined_values ($field, $group_id)
00502 {
00503 # Check whether a group field values are the default one or not.
00504 # If no entry in the database for the relevant field value belong to the
00505 # group, then it uses default values (fallback)
00506 $field_id = trackers_data_get_field_id($field);
00507 $sql="SELECT bug_fv_id FROM ".ARTIFACT."_field_value ".
00508 "WHERE group_id=".$group_id." AND bug_field_id=$field_id";
00509
00510 $result = db_query($sql);
00511 return db_numrows($result);
00512 }
00513
00514
00515 function trackers_data_is_custom($field, $by_field_id=false)
00516 {
00517 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00518 return($by_field_id ? $BF_USAGE_BY_ID[$field]['custom']: $BF_USAGE_BY_NAME[$field]['custom']);
00519 }
00520
00521 function trackers_data_is_special($field, $by_field_id=false)
00522 {
00523 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00524 return($by_field_id ? $BF_USAGE_BY_ID[$field]['special']: $BF_USAGE_BY_NAME[$field]['special']);
00525 }
00526
00527 # deprecated
00528 function trackers_data_is_empty_ok ($field, $by_field_id=false)
00529 {
00530 return trackers_data_mandatory_flag($field, $by_field_id);
00531 }
00532
00533 function trackers_data_mandatory_flag ($field, $by_field_id=false)
00534 {
00535 # 1 = not mandatory
00536 # 0 = relaxed mandatory (mandatory if it was to the submitter)
00537 # 3 = mandatory whenever possible
00538 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00539 if ($by_field_id)
00540 {
00541 $val = $BF_USAGE_BY_ID[$field]['custom_empty_ok'];
00542 if (!isset($val))
00543 { $val = $BF_USAGE_BY_ID[$field]['empty_ok']; }
00544 } else
00545 {
00546 $val = $BF_USAGE_BY_NAME[$field]['custom_empty_ok'];
00547 if (!isset($val))
00548 { $val = $BF_USAGE_BY_NAME[$field]['empty_ok']; }
00549 }
00550 return($val);
00551 }
00552
00553
00554 function trackers_data_do_keep_history($field, $by_field_id=false)
00555 {
00556 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00557 if ($by_field_id)
00558 {
00559 $val = $BF_USAGE_BY_ID[$field]['custom_keep_history'];
00560 if (!isset($val))
00561 { $val = $BF_USAGE_BY_ID[$field]['empty_keep_history']; }
00562 } else
00563 {
00564 $val = $BF_USAGE_BY_NAME[$field]['custom_keep_history'];
00565 if (!isset($val))
00566 { $val = $BF_USAGE_BY_NAME[$field]['keep_history']; }
00567 }
00568 return($val);
00569 }
00570
00571 function trackers_data_is_required($field, $by_field_id=false)
00572 {
00573 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00574 return($by_field_id ? $BF_USAGE_BY_ID[$field]['required']: $BF_USAGE_BY_NAME[$field]['required']);
00575 }
00576
00577 function trackers_data_is_used($field, $by_field_id=false)
00578 {
00579 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00580 return($by_field_id ? $BF_USAGE_BY_ID[$field]['use_it']: $BF_USAGE_BY_NAME[$field]['use_it']);
00581 }
00582
00583 function trackers_data_is_showed_on_query($field)
00584 {
00585 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00586 return($by_field_id ? $BF_USAGE_BY_ID[$field]['show_on_query']: $BF_USAGE_BY_NAME[$field]['show_on_query']);
00587
00588 }
00589
00590 function trackers_data_is_showed_on_result($field)
00591 {
00592 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00593 return($by_field_id ? $BF_USAGE_BY_ID[$field]['show_on_result']: $BF_USAGE_BY_NAME[$field]['show_on_result']);
00594 }
00595
00596 # return a TRUE value if non project members who still are
00597 # logged in users should be able to access this field
00598 # (first bit of show_on_add set)
00599 function trackers_data_is_showed_on_add($field, $by_field_id=false)
00600 {
00601 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00602 return($by_field_id ? $BF_USAGE_BY_ID[$field]['show_on_add'] & 1: $BF_USAGE_BY_NAME[$field]['show_on_add'] & 1);
00603 }
00604
00605 # return a TRUE value if non logged in users should be able to
00606 # access this field (second bit of show_on_add set)
00607 function trackers_data_is_showed_on_add_nologin($field, $by_field_id=false)
00608 {
00609 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00610 return($by_field_id ? $BF_USAGE_BY_ID[$field]['show_on_add'] & 2: $BF_USAGE_BY_NAME[$field]['show_on_add'] & 2);
00611 }
00612
00613 # return a TRUE value if project members should be able to
00614 # access this field
00615 function trackers_data_is_showed_on_add_members($field, $by_field_id=false)
00616 {
00617 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00618 return($by_field_id ? $BF_USAGE_BY_ID[$field]['show_on_add_members']: $BF_USAGE_BY_NAME[$field]['show_on_add_members']);
00619 }
00620
00621 function trackers_data_is_date_field($field, $by_field_id=false)
00622 {
00623 return(trackers_data_get_display_type($field, $by_field_id) == 'DF');
00624 }
00625
00626 function trackers_data_is_text_field($field, $by_field_id=false)
00627 {
00628 return(trackers_data_get_display_type($field, $by_field_id) == 'TF');
00629 }
00630
00631 function trackers_data_is_text_area($field, $by_field_id=false)
00632 {
00633 return(trackers_data_get_display_type($field, $by_field_id) == 'TA');
00634 }
00635
00636 function trackers_data_is_select_box($field, $by_field_id=false)
00637 {
00638 return(trackers_data_get_display_type($field, $by_field_id) == 'SB');
00639 }
00640
00641 function trackers_data_is_username_field($field, $by_field_id=false)
00642 {
00643 global $BF_USAGE_BY_ID;
00644 if ($by_field_id)
00645 {
00646 $field = trackers_data_get_field_name($field);
00647 }
00648 return(($field == 'assigned_to') || ($field == 'submitted_by'));
00649 }
00650
00651 function trackers_data_is_project_scope($field, $by_field_id=false)
00652 {
00653 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00654 if ($by_field_id)
00655 {
00656 return($BF_USAGE_BY_ID[$field]['scope'] == 'P');
00657 }
00658 else
00659 {
00660 return($BF_USAGE_BY_NAME[$field]['scope'] == 'P');
00661 }
00662 }
00663
00664 function trackers_data_is_status_closed($status)
00665 {
00666 if ($status == '3')
00667 { return 1; }
00668 return 0;
00669 }
00670
00671 function trackers_data_get_field_name($field_id)
00672 {
00673 global $BF_USAGE_BY_ID;
00674 return($BF_USAGE_BY_ID[$field_id]['field_name']);
00675 }
00676
00677 function trackers_data_get_field_id($field_name)
00678 {
00679 global $BF_USAGE_BY_NAME;
00680 return($BF_USAGE_BY_NAME[$field_name]['bug_field_id']);
00681 }
00682
00683 function trackers_data_get_group_id($field, $by_field_id=false)
00684 {
00685 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00686 return($by_field_id ? $BF_USAGE_BY_ID[$field]['group_id'] : $BF_USAGE_BY_NAME[$field]['group_id']);
00687 }
00688
00689 function trackers_data_get_label($field, $by_field_id=false)
00690 {
00691 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00692 if ($by_field_id)
00693 {
00694 $lbl = $BF_USAGE_BY_ID[$field]['custom_label'];
00695 if (!isset($lbl))
00696 { $lbl = $BF_USAGE_BY_ID[$field]['label']; }
00697 } else
00698 {
00699 $lbl = $BF_USAGE_BY_NAME[$field]['custom_label'];
00700 if (!isset($lbl))
00701 { $lbl = $BF_USAGE_BY_NAME[$field]['label']; }
00702 }
00703 return($lbl);
00704 }
00705
00706 function trackers_data_get_description($field, $by_field_id=false)
00707 {
00708 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00709 if ($by_field_id)
00710 {
00711 $desc = $BF_USAGE_BY_ID[$field]['custom_description'];
00712 if (!isset($desc))
00713 { $desc = $BF_USAGE_BY_ID[$field]['description']; }
00714 } else
00715 {
00716 $desc = $BF_USAGE_BY_NAME[$field]['custom_description'];
00717 if (!isset($desc))
00718 { $desc = $BF_USAGE_BY_NAME[$field]['description']; }
00719 }
00720 return($desc);
00721 }
00722
00723 function trackers_data_get_display_type($field, $by_field_id=false)
00724 {
00725 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00726 return($by_field_id ? $BF_USAGE_BY_ID[$field]['display_type'] : $BF_USAGE_BY_NAME[$field]['display_type']);
00727 }
00728
00729 function trackers_data_get_display_type_in_clear($field, $by_field_id=false)
00730 {
00731 if (trackers_data_is_select_box($field, $by_field_id))
00732 {
00733 return 'Select Box';
00734 }
00735 else if (trackers_data_is_text_field($field, $by_field_id))
00736 {
00737 return 'Text Field';
00738 }
00739 else if (trackers_data_is_text_area($field, $by_field_id))
00740 {
00741 return 'Text Area';
00742 }
00743 else if (trackers_data_is_date_field($field, $by_field_id))
00744 {
00745 return 'Date Field';
00746 }
00747 else
00748 {
00749 return '?';
00750 }
00751 }
00752
00753
00754 function trackers_data_get_keep_history($field, $by_field_id=false)
00755 {
00756 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00757 if ($by_field_id)
00758 {
00759 $val = $BF_USAGE_BY_ID[$field]['custom_keep_history'];
00760 if (!isset($val))
00761 { $val = $BF_USAGE_BY_ID[$field]['keep_history']; }
00762 } else
00763 {
00764 $val = $BF_USAGE_BY_NAME[$field]['custom_keep_history'];
00765 if (!isset($val))
00766 { $val = $BF_USAGE_BY_NAME[$field]['keep_history']; }
00767 }
00768 return($val);
00769 }
00770
00771 function trackers_data_get_place($field, $by_field_id=false)
00772 {
00773 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00774 return($by_field_id ? $BF_USAGE_BY_ID[$field]['place'] : $BF_USAGE_BY_NAME[$field]['place']);
00775 }
00776
00777 function trackers_data_get_scope($field, $by_field_id=false)
00778 {
00779 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00780 return($by_field_id ? $BF_USAGE_BY_ID[$field]['scope'] : $BF_USAGE_BY_NAME[$field]['scope']);
00781 }
00782
00783 function trackers_data_get_col_width($field, $by_field_id=false)
00784 {
00785 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00786 return($by_field_id ? $BF_USAGE_BY_ID[$field]['col_width'] : $BF_USAGE_BY_NAME[$field]['col_width']);
00787 }
00788
00789 function trackers_data_get_display_size($field, $by_field_id=false)
00790 {
00791 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00792 if ($by_field_id)
00793 {
00794 $val = $BF_USAGE_BY_ID[$field]['custom_display_size'];
00795 if (!isset($val))
00796 { $val = $BF_USAGE_BY_ID[$field]['display_size']; }
00797 } else
00798 {
00799 $val = $BF_USAGE_BY_NAME[$field]['custom_display_size'];
00800 if (!isset($val))
00801 { $val = $BF_USAGE_BY_NAME[$field]['display_size']; }
00802 }
00803 return(explode('/',$val));
00804 }
00805
00806 function trackers_data_get_default_value($field, $by_field_id=false)
00807 {
00808 global $BF_USAGE_BY_ID,$BF_USAGE_BY_NAME;
00809
00810
00811
00812
00813 if ($by_field_id)
00814 {
00815 $field = trackers_data_get_field_name($field);
00816 }
00817
00818 $result = db_query('describe bug '.$field);
00819 return (db_result($result,0,'Default'));
00820
00821 }
00822
00823 function trackers_data_get_max_value_id($field, $group_id, $by_field_id=false)
00824 {
00825
00826
00827
00828
00829
00830
00831 if (!$by_field_id)
00832 {
00833 $field_id = trackers_data_get_field_id($field);
00834 }
00835
00836 $sql="SELECT max(value_id) as max FROM ".ARTIFACT."_field_value ".
00837 "WHERE bug_field_id='$field_id' AND group_id='$group_id' ";
00838 $res = db_query($sql);
00839 $rows = db_numrows($res);
00840
00841 # If no max value found then it means it's the first value for this field
00842 # in this group. Return -1 in this case
00843 if ($rows == 0)
00844 {
00845 return(-1);
00846 } else
00847 {
00848 return(db_result($res,0,'max'));
00849 }
00850
00851 }
00852
00853 function trackers_data_is_value_set_empty($field, $group_id, $by_field_id=false)
00854 {
00855
00856
00857
00858
00859
00860
00861 if (!$by_field_id)
00862 {
00863 $field_id = trackers_data_get_field_id($field);
00864 }
00865 $sql="SELECT value_id FROM ".ARTIFACT."_field_value ".
00866 "WHERE bug_field_id='$field_id' AND group_id='$group_id' ";
00867 $res = db_query($sql);
00868 $rows=db_numrows($res);
00869
00870 return (($rows<=0));
00871 }
00872
00873
00874 function trackers_data_copy_default_values($field, $group_id, $by_field_id=false)
00875 {
00876
00877
00878
00879
00880
00881 if (!$by_field_id)
00882 {
00883 $field_id = trackers_data_get_field_id($field);
00884 }
00885
00886 # if group_id=100 (None) it is a null operation
00887 # because default values belong to group_id 100 by definition
00888 if ($group_id != 100)
00889 {
00890
00891 # First delete the exisiting value if any
00892 $sql="DELETE FROM ".ARTIFACT."_field_value ".
00893 "WHERE bug_field_id='$field_id' AND group_id='$group_id' ";
00894 $res = db_query($sql);
00895
00896 # Second insert default values (if any) from group 'None'
00897 # Rk: The target table of the INSERT statement cannot appear in
00898 # the FROM clause of the SELECT part of the query because it's forbidden
00899 # in ANSI SQL to SELECT . So do it by hand !
00900 #
00901
00902 $sql = "SELECT value_id,value,description,order_id,status ".
00903 "FROM ".ARTIFACT."_field_value ".
00904 "WHERE bug_field_id='$field_id' AND group_id='100'";
00905 $res = db_query($sql);
00906 $rows = db_numrows($res);
00907
00908 for ($i=0; $i<$rows; $i++)
00909 {
00910
00911 $value_id = addslashes(db_result($res,$i,'value_id'));
00912 $value = db_result($res,$i,'value');
00913 $description = addslashes(db_result($res,$i,'description'));
00914 $order_id = db_result($res,$i,'order_id');
00915 $status = db_result($res,$i,'status');
00916
00917
00918 $sql="INSERT INTO ".ARTIFACT."_field_value ".
00919 "(bug_field_id,group_id,value_id,value,description,order_id,status) ".
00920 "VALUES ('$field_id','$group_id','$value_id','$value','$description','$order_id','$status')";
00921 #print "<BR>DBG - $sql";
00922 $res_insert = db_query($sql);
00923
00924 if (db_affected_rows($res_insert) < 1)
00925 {
00926 fb(_("Insert of default value failed."), 0);
00927 db_error();
00928 }
00929 }
00930 }
00931 }
00932
00933 function trackers_data_get_cached_field_value($field,$group_id,$value_id)
00934 {
00935 global $BF_VALUE_BY_NAME;
00936
00937 if (!isset($BF_VALUE_BY_NAME[$field][$value_id]))
00938 {
00939 $res = trackers_data_get_field_predefined_values ($field, $group_id,false,false,false);
00940
00941 while ($fv_array = db_fetch_array($res))
00942 {
00943 # $fv_array[0] has the value_id and [1] is the value
00944 $BF_VALUE_BY_NAME[$field][$fv_array['value_id']] = $fv_array[1];
00945 }
00946 }
00947
00948 return $BF_VALUE_BY_NAME[$field][$value_id];
00949 }
00950
00951 function trackers_data_get_field_value ($item_fv_id)
00952 {
00953
00954
00955
00956
00957 $sql = "SELECT * FROM ".ARTIFACT."_field_value WHERE bug_fv_id='$item_fv_id'";
00958 $res = db_query($sql);
00959 return($res);
00960 }
00961
00962 function trackers_data_is_default_value ($item_fv_id)
00963 {
00964
00965
00966
00967
00968
00969 $sql = "SELECT bug_field_id,value_id FROM ".ARTIFACT."_field_value WHERE bug_fv_id='$item_fv_id' AND group_id='100'";
00970 $res = db_query($sql);
00971
00972 return ( (db_numrows($res) >= 1) ? $res : false);
00973 }
00974
00975 function trackers_data_create_value ($field, $group_id, $value, $description,$order_id,$status='A',$by_field_id=false)
00976 {
00977
00978 global $feedback,$ffeedback;
00979
00980
00981
00982
00983
00984 # An empty field value is not allowed
00985 if (preg_match ("/^\s*$/", $value))
00986 {
00987 fb(_("Empty field value not allowed"), 0);
00988 return;
00989 }
00990
00991 if (!$by_field_id)
00992 {
00993 $field_id = trackers_data_get_field_id($field);
00994 }
00995
00996 # if group_id=100 (None) then do nothing
00997 # because no real project should have the group number '100'
00998 if ($group_id != 100)
00999 {
01000
01001 # if the current value set for this project is empty
01002 # then copy the default values first (if any)
01003 if (trackers_data_is_value_set_empty($field,$group_id))
01004 {
01005 trackers_data_copy_default_values($field,$group_id);
01006 }
01007
01008 # Find the next value_id to give to this new value. (Start arbitrarily
01009 # at 200 if no value exists (and therefore max is undefined)
01010 $max_value_id = trackers_data_get_max_value_id($field, $group_id);
01011
01012 if ($max_value_id < 0)
01013 {
01014 $value_id = 200;
01015 }
01016 else
01017 {
01018 $value_id = $max_value_id +1;
01019 }
01020
01021
01022 $sql = "INSERT INTO ".ARTIFACT."_field_value ".
01023 "(bug_field_id,group_id,value_id,value,description,order_id,status) ".
01024 "VALUES ('$field_id','$group_id','$value_id','$value','$description','$order_id','$status')";
01025 db_query($sql);
01026
01027 if (db_affected_rows($result) < 1)
01028 {
01029 fb(_("Insert failed."), 0);
01030 ' - '.db_error();
01031 }
01032 else
01033
01034 {
01035 fb(_("New field value inserted."));
01036 }
01037 }
01038 }
01039
01040
01041 function trackers_data_update_value ($item_fv_id,$field,$group_id,$value,$description,$order_id,$status='A')
01042 {
01043
01044 global $feedback,$ffeedback;
01045
01046
01047
01048
01049 # An empty field value is not allowed
01050 if (preg_match ("/^\s*$/", $value))
01051 {
01052 fb(_("Empty field value not allowed"), 0);
01053 return;
01054 }
01055
01056 # Updating a bug field value that belong to group 100 (None) is
01057 # forbidden. These are default values that cannot be changed so
01058 # make sure to copy the default values first in the project context first
01059
01060 if ($res = trackers_data_is_default_value($item_fv_id))
01061 {
01062 trackers_data_copy_default_values($field,$group_id);
01063
01064 $arr = db_fetch_array($res);
01065 $where_cond = 'bug_field_id='.$arr['bug_field_id'].
01066 ' AND value_id='.$arr['value_id']." AND group_id='$group_id' ";
01067 }
01068 else
01069 {
01070 $where_cond = "bug_fv_id='$item_fv_id' AND group_id<>'100'";
01071 }
01072
01073 # Now perform the value update
01074 $sql = "UPDATE ".ARTIFACT."_field_value ".
01075 "SET value='$value',description='$description',order_id='$order_id',status='$status' ".
01076 "WHERE $where_cond";
01077 $result = db_query($sql);
01078
01079 #print "<BR>DBG - $sql";
01080
01081 if (db_affected_rows($result) < 1)
01082 {
01083 fb(_("Update of field value failed."));
01084 }
01085 else
01086 {
01087 fb(_("New field value updated."));
01088 }
01089 }
01090
01091 function trackers_data_reset_usage($field_name,$group_id)
01092 {
01093 global $feedback;
01094
01095
01096
01097
01098
01099 $field_id = trackers_data_get_field_id($field_name);
01100 if ($group_id != 100)
01101 {
01102 $sql = "DELETE FROM ".ARTIFACT."_field_usage ".
01103 "WHERE group_id='$group_id' AND bug_field_id='$field_id'";
01104 db_query($sql);
01105 fb(_("Field value successfully reset to defaults."));
01106
01107 }
01108 }
01109
01110 function trackers_data_update_usage($field_name,
01111 $group_id,
01112 $label,
01113 $description,
01114 $use_it,
01115 $rank,
01116 $display_size,
01117 $empty_ok,
01118 $keep_history,
01119 $show_on_add_members=0,
01120 $show_on_add=0,
01121 $transition_default_auth='A')
01122
01123 {
01124
01125
01126
01127
01128
01129
01130
01131
01132 # if it's a required field then make sure the use_it flag is true
01133 if (trackers_data_is_required($field_name))
01134 {
01135 $use_it = 1;
01136 }
01137
01138 $field_id = trackers_data_get_field_id($field_name);
01139
01140 # if it's a custom field then take label into account else store NULL
01141 # if (trackers_data_is_custom($field_name)) {
01142 $lbl = isset($label) ? "'$label'" : 'NULL';
01143 $desc = isset($description) ? "'$description'" : 'NULL';
01144 $disp_size = isset($display_size) ? "'$display_size'" : 'NULL';
01145 $empty = isset($empty_ok) ? "'$empty_ok'" : 'NULL';
01146 $keep_hist = isset($keep_history) ? "'$keep_history'" : 'NULL';
01147 # } else {
01148 # $lbl = $desc = $disp_size = $empty = $keep_hist = "NULL";
01149 # }
01150
01151 # See if this field usage exists in the table for this project
01152 $sql = 'SELECT bug_field_id FROM '.ARTIFACT.'_field_usage '.
01153 "WHERE bug_field_id='$field_id' AND group_id='$group_id'";
01154 $result = db_query($sql);
01155 $rows = db_numrows($result);
01156
01157 # if it does exist then update it else insert a new usage entry for this field.
01158 if ($rows)
01159 {
01160 $sql = 'UPDATE '.ARTIFACT.'_field_usage '.
01161 "SET use_it='$use_it',show_on_add='$show_on_add',".
01162 "show_on_add_members='$show_on_add_members',place='$rank', ".
01163 "custom_label=$lbl, custom_description=$desc,".
01164 "custom_display_size=$disp_size, custom_empty_ok=$empty,".
01165 "custom_keep_history=$keep_hist, ".
01166 "transition_default_auth='$transition_default_auth' ".
01167 "WHERE bug_field_id='$field_id' AND group_id='$group_id'";
01168 $result = db_query($sql);
01169 }
01170 else
01171 {
01172 $sql = 'INSERT INTO '.ARTIFACT.'_field_usage '.
01173 "VALUES ('$field_id','$group_id','$use_it','$show_on_add',".
01174 "'$show_on_add_members','$rank',$lbl,$desc,$disp_size,$empty,$keep_hist,'$transition_default_auth')";
01175 $result = db_query($sql);
01176 }
01177
01178 if (db_affected_rows($result) < 1)
01179 { fb(_("Update of field usage failed."), 1); }
01180 else
01181 { fb(_("Field usage updated.")); }
01182
01183 }
01184
01185 # Get a list of technicians for a tracker
01186 function trackers_data_get_technicians ($group_id)
01187 {
01188 # FIXME: The cleanest thing would be to issue one SQL command.
01189 # But we have to handle the fact that "no setting" = get back
01190 # to the group, or even group type, setting.
01191
01192 # In fact, this is terrible, we cannot return something else than
01193 # a mysql result if we do not want to rewrite 25 functions.
01194 # So we get the appropriate list of users... and finally issue a
01195 # mysql command only to be able to return a mysql result.
01196 # Please, propose something better at savannah-dev@gnu.org
01197
01198
01199 # Get list of members
01200 $members_sql = "SELECT user.user_id AS user_id "
01201 . "FROM user,user_group "
01202 . "WHERE user.user_id=user_group.user_id AND user_group.group_id=$group_id ";
01203 $members_res = db_query($members_sql);
01204 # Build the sql command
01205 $sql = "SELECT user_id,user_name FROM user WHERE ";
01206 while ($member = db_fetch_array($members_res))
01207 {
01208 if (member_check($member['user_id'], $group_id, member_create_tracker_flag(ARTIFACT).'1'))
01209 {
01210 if ($notfirst)
01211 { $sql .= " OR "; }
01212 $sql .= " user_id='".$member['user_id']."'";
01213 $notfirst = 1;
01214 }
01215 }
01216 $sql .= " ORDER BY user_name";
01217 return db_query($sql);
01218 }
01219
01220 # Get transitions valid for a given tracker as an array
01221 # DEPRECATED, moved to transition.php
01222 function trackers_data_get_transition ($group_id)
01223 {
01224 return trackers_transition_get_update($group_id);
01225 }
01226
01227 function trackers_data_get_submitters ($group_id=false)
01228 {
01229 $sql="SELECT DISTINCT user.user_id,user.user_name ".
01230 "FROM user,".ARTIFACT." ".
01231 "WHERE user.user_id=".ARTIFACT.".submitted_by ".
01232 "AND ".ARTIFACT.".group_id='$group_id' ".
01233 "ORDER BY user.user_name";
01234 return db_query($sql);
01235 }
01236
01237 function trackers_data_get_items ($group_id=false, $artifact)
01238 {
01239
01240
01241
01242 $sql="SELECT bug_id,summary ".
01243 "FROM ".$artifact." ".
01244 "WHERE group_id='".$group_id."'".
01245 " AND status_id <> '3' ".
01246 " ORDER BY bug_id DESC LIMIT 100";
01247 return db_query($sql);
01248 }
01249
01250 function trackers_data_get_dependent_items ($item_id=false, $artifact, $notin=false)
01251 {
01252
01253
01254
01255 $sql="SELECT is_dependent_on_item_id FROM ".ARTIFACT."_dependencies WHERE item_id='$item_id' AND is_dependent_on_item_id_artifact='".$artifact."' ";
01256 if ($notin)
01257 {
01258 $sql .= ' AND is_dependent_on_item_id NOT IN ('. join(',',$notin).')';
01259 }
01260 # print $sql; #DBG
01261 return db_query($sql);
01262 }
01263
01264 function trackers_data_get_valid_bugs ($group_id=false,$item_id='')
01265 {
01266 $sql="SELECT bug_id,summary ".
01267 "FROM ".ARTIFACT." ".
01268 "WHERE group_id='$group_id' ".
01269 "AND bug_id <> '$item_id' AND ".ARTIFACT.".resolution_id <> '2' ORDER BY bug_id DESC LIMIT 200";
01270 return db_query($sql);
01271 }
01272
01273 function trackers_data_get_followups ($item_id=false, $rorder=true)
01274 {
01275 if ($rorder == "true")
01276 { $rorder = "DESC"; }
01277 else
01278 { $rorder = "ASC"; }
01279
01280 $sql="SELECT DISTINCT ".ARTIFACT."_history.bug_history_id,".ARTIFACT."_history.field_name,".ARTIFACT."_history.old_value,".ARTIFACT."_history.date,user.user_name,user.realname,".ARTIFACT."_field_value.value AS comment_type ".
01281 "FROM ".ARTIFACT."_history,".ARTIFACT."_field_value,".ARTIFACT."_field,".ARTIFACT.",user ".
01282 "WHERE ".ARTIFACT."_history.bug_id='$item_id' ".
01283 "AND ".ARTIFACT."_history.field_name = 'details' ".
01284 "AND ".ARTIFACT."_history.mod_by=user.user_id ".
01285 "AND ".ARTIFACT."_history.bug_id=".ARTIFACT.".bug_id ".
01286 "AND ".ARTIFACT."_history.type = ".ARTIFACT."_field_value.value_id ".
01287 "AND ".ARTIFACT."_field_value.bug_field_id = ".ARTIFACT."_field.bug_field_id ".
01288 "AND (".ARTIFACT."_field_value.group_id = ".ARTIFACT.".group_id OR ".ARTIFACT."_field_value.group_id = '100') ".
01289 "AND ".ARTIFACT."_field.field_name = 'comment_type_id' ".
01290 "ORDER BY ".ARTIFACT."_history.date $rorder";
01291
01292 return db_query($sql);
01293 }
01294
01295 function trackers_data_get_commenters($item_id)
01296 {
01297 $sql="SELECT DISTINCT mod_by FROM ".ARTIFACT."_history ".
01298 "WHERE ".ARTIFACT."_history.bug_id='$item_id' ".
01299 "AND ".ARTIFACT."_history.field_name = 'details' ";
01300 return db_query($sql);
01301 }
01302
01303 function trackers_data_get_history ($item_id=false)
01304 {
01305 $sql="select ".ARTIFACT."_history.field_name,".ARTIFACT."_history.old_value,".ARTIFACT."_history.date,".ARTIFACT."_history.type,user.user_name,".ARTIFACT."_history.new_value ".
01306 "FROM ".ARTIFACT."_history,user ".
01307 "WHERE ".ARTIFACT."_history.mod_by=user.user_id ".
01308 "AND ".ARTIFACT."_history.field_name <> 'details' ".
01309 "AND bug_id='$item_id' ORDER BY ".ARTIFACT."_history.date DESC";
01310 return db_query($sql);
01311 }
01312
01313 function trackers_data_get_attached_files ($item_id=false, $order='DESC')
01314 {
01315 $sql="SELECT file_id,filename,filesize,filetype,description,date,user.user_name ".
01316 "FROM trackers_file,user ".
01317 "WHERE submitted_by=user.user_id ".
01318 "AND artifact='".ARTIFACT."' ".
01319 "AND item_id='$item_id' ORDER BY date $order";
01320 return db_query($sql);
01321 }
01322
01323 function trackers_data_get_cc_list ($item_id=false)
01324 {
01325 $sql="SELECT bug_cc_id,".ARTIFACT."_cc.email,".ARTIFACT."_cc.added_by,".ARTIFACT."_cc.comment,".ARTIFACT."_cc.date,user.user_name ".
01326 "FROM ".ARTIFACT."_cc,user ".
01327 "WHERE added_by=user.user_id ".
01328 "AND bug_id='$item_id' ORDER BY date DESC";
01329 return db_query($sql);
01330 }
01331
01332 function trackers_data_add_history ($field_name,
01333 $old_value,
01334 $new_value,
01335 $item_id,
01336 $type=false,
01337 $artifact=0,
01338 $force=0)
01339
01340 {
01341
01342 # If no artifact is defined, get the default one
01343 if (!$artifact)
01344 {
01345 $artifact = ARTIFACT;
01346 }
01347
01348 # If field is not to be kept in bug change history then do nothing
01349 if (!$force && !trackers_data_get_keep_history($field_name))
01350 { return; }
01351
01352 if (!user_isloggedin())
01353 {
01354 $user=100;
01355 }
01356 else
01357 {
01358 $user=user_getid();
01359 }
01360
01361 # If type has a value add it into the sql statement (this is only for
01362 # the follow up comments (details field))
01363 if ($type)
01364 {
01365 $fld_type = ',type'; $val_type = ",'$type'";
01366 }
01367 else
01368 {
01369 # No comment type specified for a followup comment
01370 # so force it to None (100)
01371 if ($field_name == 'details')
01372 {
01373 $fld_type = ',type'; $val_type = ",'100'";
01374 }
01375 }
01376
01377
01378 $sql="INSERT INTO ".$artifact."_history (bug_id,field_name,old_value,new_value,mod_by,date $fld_type) ".
01379 "VALUES ('$item_id','$field_name','$old_value','$new_value','$user','".time()."' $val_type)";
01380 return db_query($sql);
01381 }
01382
01383
01384 # Handles update of most usual fields.
01385 function trackers_data_handle_update ($group_id,
01386 $item_id,
01387 $dependent_on_task,
01388 $dependent_on_bugs,
01389 $dependent_on_support,
01390 $dependent_on_patch,
01391 $canned_response,
01392 $vfl,
01393 &$changes,
01394 &$extra_addresses)
01395 {
01396 # variable to track changes made inside the function
01397 $change_exists = false;
01398
01399 # Update an item. Rk: vfl is an variable list of fields, Vary from one
01400 # project to another
01401 # return true if bug updated, false if nothing changed or
01402 # DB update failed
01403
01404 # Make sure absolutely required fields are not empty
01405 # yeupou, 2005-11: why is canned_response absolutely required?
01406 if (!$group_id || !$item_id || !$canned_response)
01407 {
01408 dbg("params were group_id:$group_id item_id:$item_id canned_response:$canned_response");
01409 exit_missing_param();
01410 }
01411
01412 # Make sure mandatory fields are not empty, otherwise we want the form
01413 # to be re-submitted
01414 if ((trackers_check_empty_fields($vfl, false) == false))
01415 {
01416 # In such circonstances, we reprint the form
01417 # highligthing missing fields.
01418 # (It is important that trackers_check_empty_fields set the global var
01419 # previous_form_bad_fields)
01420 return false;
01421 }
01422
01423 # Get this bug from the db
01424
01425 $sql="SELECT * FROM ".ARTIFACT." WHERE bug_id='$item_id'";
01426 $result=db_query($sql);
01427
01428 if (!((db_numrows($result) > 0) && (member_check(0,db_result($result,0,'group_id'), member_create_tracker_flag(ARTIFACT).'2'))))
01429 {
01430 # Verify permissions
01431 dbg("no management/techn. rights");
01432 exit_permission_denied();
01433 }
01434
01435 # Extract field transitions possibilities:
01436 $field_transition = array();
01437 $field_transition = trackers_data_get_transition($group_id);
01438 # We will store in an array the transition_id accepted, to check
01439 # other fields updates
01440 $field_transition_accepted = array();
01441
01442 # See which fields changed during the modification
01443 # and if we must keep history then do it. Also add them to the update
01444 # statement
01445 $changes = array();
01446 reset($vfl);
01447 while (list($field,$value) = each($vfl))
01448 {
01449 # $field_transition_id needed to be reset for every field in the loop
01450 # and $field_transition_accepted filled only if $field_transition_id
01451 # is not empty (otherwise transition automatic updates risk to be
01452 # done by error if a transition is defined for any field!)
01453 unset($field_transition_id);
01454
01455 # skip over special fields except for summary which in this
01456 # particular case can be processed normally
01457 if (trackers_data_is_special($field) && ($field != 'summary'))
01458 { continue; }
01459
01460 # skip over comment, which is also a special field but not known as
01461 # special by the database
01462 if ($field == 'comment')
01463 { continue; }
01464
01465 $old_value = db_result($result,0,$field);
01466
01467 # Handle field transitions checks+cc notif,
01468 # register id of transition to execute
01469 # yeupou--gnu.org 2004-09-12: where the hell $by_field_id is set???
01470 $field_id = ($by_field_id ? $field : trackers_data_get_field_id($field));
01471 $field_transition_cc = '';
01472 if (array_key_exists($field_id, $field_transition))
01473 {
01474 # First check basic transition
01475 # And check multiple transition, override other transition
01476 if (array_key_exists($old_value, $field_transition[$field_id])||
01477 array_key_exists("any", $field_transition[$field_id]))
01478 {
01479 if (array_key_exists("any", $field_transition[$field_id]) && array_key_exists($value, $field_transition[$field_id]["any"]))
01480 {
01481 $field_transition_cc = $field_transition[$field_id]["any"][$value]['notification_list'];
01482
01483 # Register the transition, but only if the field it is about
01484 # was not filled in the form
01485 if (!is_array($changes[$field]) ||
01486 (!array_key_exists('del', $changes[$field]) &&
01487 !array_key_exists('add', $changes[$field])))
01488 {
01489
01490 $field_transition_id = $field_transition[$field_id]["any"][$value]['transition_id'];
01491 }
01492 }
01493 else if (array_key_exists($old_value, $field_transition[$field_id]) && array_key_exists($value, $field_transition[$field_id][$old_value]))
01494 {
01495
01496 $field_transition_cc = $field_transition[$field_id][$old_value][$value]['notification_list'];
01497
01498 # Register the transition, but only if the field it is about
01499 # was not filled in the form
01500 if (!is_array($changes[$field]) ||
01501 (!array_key_exists('del', $changes[$field]) &&
01502 !array_key_exists('add', $changes[$field])))
01503 {
01504 $field_transition_id = $field_transition[$field_id][$old_value][$value]['transition_id'];
01505 }
01506
01507 }
01508
01509 }
01510 }
01511
01512 $is_text = (trackers_data_is_text_field($field) || trackers_data_is_text_area($field));
01513 if ($is_text)
01514 {
01515 $differ = ($old_value != stripslashes(htmlspecialchars($value)));
01516 }
01517 else if (trackers_data_is_date_field($field))
01518 {
01519 # if it is a date we must convert the format to unix time
01520 $date_value = $value;
01521 list($value,$ok) = utils_date_to_unixtime($value);
01522
01523 # Users can be on different timezone ; The form
01524 # save only the day, month, year.
01525 # We cannot compare the timestamp (affected by timezone changes)
01526 $date_old_value = date("Y-n-j", $old_value);
01527
01528 $differ = ($date_old_value != $date_value);
01529 }
01530 else
01531 {
01532 $differ = ($old_value != $value);
01533 }
01534
01535 if ($differ)
01536 {
01537
01538 if ((trim($extra_addresses) != "") && (trim($field_transition_cc) != ""))
01539 {
01540 $extra_addresses .= ", ";
01541 }
01542 $extra_addresses .= $field_transition_cc;
01543
01544
01545 if ($is_text)
01546 {
01547 $upd_list .= "$field='".htmlspecialchars($value)."',";
01548 trackers_data_add_history($field,
01549 addslashes($old_value),
01550 $value,
01551 $item_id);
01552 $value = stripslashes($value);
01553 }
01554 else
01555 {
01556 $upd_list .= "$field='$value',";
01557 trackers_data_add_history($field,$old_value,$value,$item_id);
01558 }
01559
01560 # Keep track of the change
01561 $changes[$field]['del']=
01562 trackers_field_display($field,$group_id,$old_value,false,false,true,true);
01563 $changes[$field]['add']=
01564 trackers_field_display($field,$group_id,$value,false,false,true,true);
01565
01566 # Register transition id, if not empty
01567 if ($field_transition_id != '')
01568 {
01569 $field_transition_accepted[] = $field_transition_id;
01570 }
01571 }
01572 }
01573
01574 # Now we run transitions other fields update. This function does check
01575 # what already changed and that we wont automatically update
01576 trackers_transition_update_item($item_id, $field_transition_accepted, $changes);
01577
01578 # Comments field history is handled a little differently. Followup comments
01579 # are added in the bug history along with the comment type.
01580 # Comments are called 'details' here for historical reason.
01581 $details = $vfl['comment'];
01582 if ($canned_response != 100)
01583 {
01584 if ($details)
01585 {
01586 # Add a separator between user sbumitted comment and canned
01587 # response
01588 $details .= "\n\n";
01589 }
01590
01591 # Make sure we have an array even for a unique answer
01592 if (!is_array($canned_response))
01593 {
01594 $tempvalue = $canned_response;
01595 $canned_response = array();
01596 $canned_response[] = $tempvalue;
01597 unset($tempvalue);
01598 }
01599
01600 # Browse the canned responses
01601 while (list(,$thiscanned) = each($canned_response))
01602 {
01603
01604 $sql="SELECT * FROM ".ARTIFACT."_canned_responses WHERE bug_canned_id='".addslashes($thiscanned)."'";
01605 $res3=db_query($sql);
01606
01607 if ($res3 && db_numrows($res3) > 0)
01608 {
01609 # add a data separator
01610 if ($details)
01611 { $details .= "\n\n"; }
01612 $details .= addslashes(utils_unconvert_htmlspecialchars(db_result($res3,0,'body')));
01613 fb(_("Canned response used"));
01614 }
01615 else
01616 {
01617 fb(_("Unable to use canned response"), 0);
01618 }
01619 }
01620 }
01621
01622 # Comment field history is handled a little differently. Followup comments
01623 # are added in the bug history along with the comment type.
01624 if ($details != '')
01625 {
01626 $change_exists = 1;
01627 trackers_data_add_history('details',
01628 htmlspecialchars($details),
01629 '',
01630 $item_id,
01631 $vfl['comment_type_id']);
01632 $changes['details']['add'] = stripslashes($details);
01633 $changes['details']['type'] =
01634 trackers_data_get_value('comment_type_id',$group_id, $vfl['comment_type_id']);
01635 }
01636
01637 # If we are on the cookbook, the original submission have been details
01638 if (ARTIFACT == 'cookbook')
01639 {
01640 $details = $vfl['details'];
01641 $previous_details = db_result($result,0,'details');
01642
01643 if ($details != $previous_details)
01644 {
01645 $change_exists = 1;
01646 $upd_list .= "details='".safeinput($details)."',";
01647
01648 # We should use "details" but since details are used for comment
01649 # (which is really nasty), we simply cant.
01650
01651 # How should be print the change?
01652 # The way we do it here is to show the previous recipe cut to 25 chars
01653 # and after the -> we say the number of characters that have been added
01654 $del_cut = utils_cutstring($previous_details, 25);
01655 $change = strlen($details)-strlen($previous_details);
01656 if ($change >= 0)
01657 { $change = "+".$change; }
01658 $change .= " chars";
01659
01660 trackers_data_add_history('realdetails',
01661 htmlspecialchars($del_cut),
01662 htmlspecialchars($change),
01663 $item_id,
01664 false,
01665 false,
01666 true);
01667 $changes['realdetails']['add'] = stripslashes($change);
01668 $changes['realdetails']['del'] = stripslashes($del_cut);
01669
01670 }
01671 }
01672
01673
01674 # Enter the timestamp if we are changing to closed or declined
01675 if (trackers_data_is_status_closed($vfl['status_id']))
01676 {
01677 $now=time();
01678 $upd_list .= "close_date='$now',";
01679 trackers_data_add_history ('close_date',
01680 db_result($result,0,'close_date'),
01681 $now,
01682 $item_id);
01683 }
01684
01685 # Enter new dependancies
01686 $artifacts = array("support", "bugs", "task", "patch");
01687 while (list(, $dependent_on) = each($artifacts))
01688 {
01689 $art = $dependent_on;
01690 $dependent_on = "dependent_on_".$dependent_on;
01691 if ($$dependent_on)
01692 {
01693 while (list(, $dep) = each($$dependent_on))
01694 {
01695 trackers_data_update_dependent_items($dep, $item_id, $art);
01696
01697 $changes['Depends on']['add'] = $art." #".$dep;
01698 $change_exists = 1;
01699
01700 # Check if we're supposed to send all modifications to an address
01701 list($address, $sendall) = trackers_data_get_item_notification_info($dep, $art, 1);
01702 if (($sendall == 1) && (trim($address) != ""))
01703 {
01704 if (trim($extra_addresses) != "")
01705 {
01706 $extra_addresses .= ", ";
01707 }
01708 $extra_addresses .= $address;
01709 }
01710 }
01711 }
01712 }
01713
01714 # If we are on the cookbook, Store related links
01715 if (ARTIFACT == 'cookbook')
01716 {
01717 cookbook_handle_update($item_id, $group_id);
01718 }
01719
01720 # Finally, build the full SQL query and update the bug itself (if need be)
01721 dbg("UPD LIST: $upd_list");
01722 if ($upd_list)
01723 {
01724 # strip the excess comma at the end of the update field list
01725 $upd_list = rtrim($upd_list, ",");
01726
01727 $sql="UPDATE ".ARTIFACT." SET $upd_list ".
01728 " WHERE bug_id='$item_id' AND group_id='$group_id'";
01729 $result=db_affected_rows(db_query($sql));
01730 }
01731 else
01732 {
01733 if (!$change_exists)
01734 {
01735 fb(_("No field to update"));
01736 # must return false, otherwise a notif would be sent
01737 return false;
01738 }
01739 else
01740 {
01741 return true;
01742 }
01743 }
01744
01745 if (!$result)
01746 {
01747 exit_error(_("Item Update failed"));
01748 return false;
01749 }
01750 else
01751 {
01752 fb(_("Item Successfully Updated"));
01753 return true;
01754 }
01755
01756 }
01757
01758 function trackers_data_reassign_item ($item_id,
01759 $reassign_change_project,
01760 $reassign_change_artifact)
01761 {
01762
01763 global $group_id;
01764
01765 # Can only be done by a tracker manager
01766 if (member_check(0,$group_id, member_create_tracker_flag(ARTIFACT).'2'))
01767 {
01768 # If the new group_id is equal to the current one, nothing need
01769 # to be done, unless the artifact changed.
01770 # If the new group_id does not exists, nothing to be done either,
01771 # unless the artifact changed: if no new valid group_id, let
01772 # consider that it does not require a change.
01773 $new_group_id = group_getid($reassign_change_project);
01774 if (!$new_group_id)
01775 {
01776 $new_group_id = $group_id;
01777 }
01778
01779
01780 if ($new_group_id == $group_id && ARTIFACT == $reassign_change_artifact)
01781 {
01782 fb(_("No reassignation required or possible."));
01783 break;
01784 }
01785
01786 $now=time();
01787
01788 # To reassign an item, we close the item and we reopen a new one
01789 # at the appropriate place, copying information from the previous one
01790
01791 # Fetch all the information
01792 $sql = "SELECT * FROM ".ARTIFACT." WHERE bug_id='".$item_id."'";
01793 $res_data = db_query($sql);
01794 $row_data = db_fetch_array($res_data);
01795
01796 # Duplicate the report
01797 if (!$reassign_change_project)
01798 { $reassign_change_project = $group_id; }
01799
01800 if (!$reassign_change_artifact)
01801 {
01802 fb(_("Unable to find out to which artifact the item is to be reassigned, exiting."), 1);
01803 return 0;
01804 }
01805
01806 # move item
01807 $result = db_query("INSERT INTO ".$reassign_change_artifact.
01808 " (group_id,status_id,date,severity,submitted_by,summary,details,priority,planned_starting_date,planned_close_date,percent_complete)".
01809 " VALUES ".
01810 "(".$new_group_id.",'".
01811 "1','".
01812 $now."','".
01813 $row_data['severity']."','".
01814 $row_data['submitted_by']."','".
01815 "Reassigned item: ".addslashes($row_data['summary'])."','".
01816 addslashes($row_data['details'])."','".
01817 $row_data['priority']."','".
01818 $row_data['planned_starting_date']."','".
01819 $row_data['planned_close_date']."','".
01820 $row_data['percent_complete']."')");
01821
01822 if (!$result)
01823 {
01824 fb(_("Unable to create a new item."), 1);
01825 return 0;
01826 }
01827 else
01828 {
01829 fb(_("New item created."));
01830 }
01831
01832
01833 # Need to get the new item value
01834 $new_item_id = mysql_insert_id();
01835
01836 # Update item history
01837 trackers_data_add_history('Reassign Item',
01838 'From group '.group_getname($group_id).', '.ARTIFACT.' tracker',
01839 'To group '.group_getname($new_group_id).', '.$reassign_change_artifact.' tracker',
01840 $item_id,
01841 false,
01842 ARTIFACT,
01843 1);
01844
01845 trackers_data_add_history('Reassign item',
01846 'From group '.group_getname($group_id).', '.ARTIFACT.' tracker',
01847 'To group '.group_getname($new_group_id).', '.$reassign_change_artifact.' tracker',
01848 $new_item_id,
01849 false,
01850 $reassign_change_artifact,
01851 1);
01852
01853 if (!$new_item_id)
01854 {
01855 fb(_("Unable to find the ID of the new item."), 1);
01856 return 0;
01857 }
01858
01859 # Duplicate the comments
01860 $sql = "SELECT * FROM ".ARTIFACT."_history WHERE bug_id='".$item_id."' AND type='100'";
01861 $res_history = db_query($sql);
01862 while ($row_history = db_fetch_array($res_history))
01863 {
01864 $sql = "INSERT INTO ".$reassign_change_artifact."_history ".
01865 "(bug_id,field_name,old_value,mod_by,date,type) ".
01866 "VALUES ".
01867 "('".$new_item_id."','".
01868 $row_history['field_name']."','".
01869 addslashes($row_history['old_value'])."','".
01870 $row_history['mod_by']."','".
01871 $row_history['date']."','".
01872 $row_history['type']."')";
01873
01874 $result = db_query($sql);
01875
01876 if (!$result)
01877 {
01878 fb(_("Unable to duplicate a comment from the original item report information."), 1);
01879 }
01880 }
01881
01882 # Add a comment giving every original information
01883 $comment = "This item has been reassigned from the project ".group_getname($row_data['group_id'])." ".ARTIFACT." tracker to your tracker.\n\nThe original report is still available at ".ARTIFACT." #$item_id\n\nFollowing are the information included in the original report:\n\n";
01884
01885 $sql = "SHOW COLUMNS FROM ".ARTIFACT;
01886 $res_show = db_query($sql);
01887 $list = array();
01888 while ($row_show = db_fetch_array($res_show))
01889 {
01890 # Build a list of any possible field
01891 $list[] = $row_show['Field'];
01892 }
01893
01894 while (list($l,$v) = each($list))
01895 {
01896 if ($row_data[$l])
01897 {
01898 $comment .= "[field #".$l."] ";
01899 $comment .= trackers_field_display($v,
01900 $group_id,
01901 $row_data[$l],
01902 false,
01903 true,
01904 true, #6
01905 true);
01906 $comment .= "<br />";
01907 }
01908 }
01909
01910 # Make sure there's no \' remaining
01911 $comment = ereg_replace("'", " ", $comment);
01912
01913 $sql = "INSERT INTO ".$reassign_change_artifact."_history ".
01914 "(bug_id,field_name,old_value,mod_by,date,type)".
01915 " VALUES ".
01916 "('".$new_item_id."',".
01917 "'details',".
01918 "'".addslashes($comment)."',".
01919 "'".user_getid()."',".
01920 "'".$now."',".
01921 "'100')";
01922
01923 $result = db_query($sql);
01924
01925 if (!$result)
01926 {
01927 fb(_("Unable to add a comment with the original item report information."), 0);
01928 }
01929
01930 # Usually, reassigning means duplicating data.
01931 # In case of attached files, we simply reassign the file to another
01932 # item. This could avoid wasting too much disk space as file are expected
01933 # to be much bigger than CC list and alike.
01934 $sql = "UPDATE trackers_file SET item_id='".$new_item_id."', artifact='".$reassign_change_artifact."' WHERE item_id='".$item_id."' AND artifact='".ARTIFACT."'";
01935 $result = db_query($sql);
01936 if (!$result)
01937 {
01938 fb(sprintf(_("Unable to duplicate an attached file (%s) from the original item report information."), $row_attachment['filename']), 1);
01939 dbg("sql: $sql");
01940 }
01941
01942 # Duplicate CC List
01943 $sql = "SELECT * FROM ".ARTIFACT."_cc WHERE bug_id='".$item_id."'";
01944 $res_cc = db_query($sql);
01945 while ($row_cc = db_fetch_array($res_cc))
01946 {
01947 $sql = "INSERT INTO ".$reassign_change_artifact."_cc ".
01948 "(bug_id,email,added_by,comment,date) ".
01949 "VALUES ".
01950 "('".$new_item_id."','".
01951 $row_cc['email']."','".
01952 $row_cc['added_by']."','".
01953 addslashes($row_cc['comment'])."','".
01954 $row_cc['date']."')";
01955
01956 $result = db_query($sql);
01957
01958 if (!$result)
01959 {
01960 fb(sprintf(_("Unable to duplicate a CC address (%s) from the original item report information."), $row_cc['email']), 1);
01961 }
01962 }
01963
01964 # Close the original item
01965 $result = db_query("UPDATE ".ARTIFACT." SET status_id='3',close_date='".$now."' WHERE bug_id='".$item_id."'");
01966 trackers_data_add_history('close_date',$now,$now,$item_id);
01967
01968 if (!$result)
01969 {
01970 fb(_("Unable to close the original item report."), 1);
01971 }
01972 else
01973 {
01974 fb(_("Original item is now closed."));
01975 }
01976 }
01977
01978 }
01979
01980 function trackers_data_update_dependent_items ($depends_on, $item_id, $artifact)
01981 {
01982 global $feedback,$ffeedback;
01983
01984 # Check if the dependancy does not already exists.
01985 $sql = "SELECT item_id FROM ".ARTIFACT."_dependencies WHERE item_id='".$item_id."' AND is_dependent_on_item_id='".$depends_on."' AND is_dependent_on_item_id_artifact='".$artifact."'";
01986
01987 # If there is no dependancy know, insert it.
01988 if (!db_numrows(db_query($sql)))
01989 {
01990 $sql="INSERT INTO ".ARTIFACT."_dependencies VALUES ('$item_id','$depends_on', '$artifact')";
01991 $result=db_query($sql);
01992 if (!$result)
01993 {
01994 fb(_("Error inserting dependancy"), 1);
01995 }
01996 else
01997 {
01998 fb(_("Dependency added"));
01999 trackers_data_add_history("Dependencies",
02000 "-",
02001 "Depends on ".$artifact." #".$depends_on,
02002 $item_id,
02003 0,0,1);
02004 trackers_data_add_history("Dependencies",
02005 "-",
02006 ARTIFACT." #".$item_id." is dependent",
02007 $depends_on,
02008 0,0,1);
02009 }
02010 }
02011 }
02012
02013 # yeupou--gnu.org 2004-11-10: this function should probably removed
02014 # and handle_update be used instead.
02015 function trackers_data_create_item($group_id,$vfl,&$extra_addresses)
02016 {
02017
02018 #we dont force them to be logged in to submit a bug
02019 if (!user_isloggedin())
02020 { $user=100; }
02021 else
02022 { $user=user_getid(); }
02023
02024 # make sure required fields are not empty
02025 if (trackers_check_empty_fields($vfl) == false)
02026 {
02027 # In such circonstances, we reprint the form
02028 # highligthing missing fields.
02029 # (It is important that trackers_check_empty_fields set the global var
02030 # previous_form_bad_fields)
02031 return false;
02032 }
02033
02034 # Finally, create the bug itself
02035 # Remark: this SQL query only sets up the values for fields used by
02036 # this project. For other unused fields we assume that the DB will set
02037 # up an appropriate default value (see bug table definition)
02038
02039 # Extract field transitions possibilities:
02040 $field_transition = array();
02041 $field_transition = trackers_data_get_transition($group_id);
02042 # We will store in an array the transition_id accepted, to check
02043 # other fields updates
02044 $field_transition_accepted = array();
02045 $changes = array();
02046
02047 # Build the variable list of fields and values
02048 # Remark: we must add open/closed by ourselves, as it is missing from the
02049 # form for obvious reasons while automatic transitions may rely on its
02050 # presence
02051 $vfl['status_id'] = '1';
02052 reset($vfl);
02053 while (list($field,$value) = each($vfl))
02054 {
02055 if (trackers_data_is_special($field))
02056 { continue; }
02057
02058 # If value is the special string default,*
02059 # take the default from the database
02060 if ($value == "!unknown!")
02061 { continue; }
02062
02063 # COPIED from handle_update transition code, with one exception:
02064 # old_value is equal to "none".
02065 # handle field transitions checks/changes
02066 # yeupou--gnu.org 2004-09-12: where the hell $by_field_id is set???
02067 $field_id = ($by_field_id ? $field : trackers_data_get_field_id($field));
02068 $field_transition_cc = '';
02069 if (array_key_exists($field_id, $field_transition))
02070 {
02071 # First check basic transition
02072 # And check multiple transition, override other transition
02073 if (array_key_exists("100", $field_transition[$field_id])||
02074 array_key_exists("any", $field_transition[$field_id]))
02075 {
02076 if (array_key_exists("any", $field_transition[$field_id]) && array_key_exists($value, $field_transition[$field_id]["any"]))
02077 {
02078 $field_transition_cc = $field_transition[$field_id]["any"][$value]['notification_list'];
02079
02080 # Register the transition, but only if the field it is about
02081 # was not filled in the form
02082 if (!is_array($changes[$field]) ||
02083 (!array_key_exists('del', $changes[$field]) &&
02084 !array_key_exists('add', $changes[$field])))
02085 {
02086
02087 $field_transition_id = $field_transition[$field_id]["any"][$value]['transition_id'];
02088 }
02089 }
02090 else if (array_key_exists("100", $field_transition[$field_id]) && array_key_exists($value, $field_transition[$field_id]["100"]))
02091 {
02092
02093 $field_transition_cc = $field_transition[$field_id]["100"][$value]['notification_list'];
02094 # Register the transition, but only if the field it is about
02095 # was not filled in the form
02096 if (!is_array($changes[$field]) ||
02097 (!array_key_exists('del', $changes[$field]) &&
02098 !array_key_exists('add', $changes[$field])))
02099 {
02100 $field_transition_id = $field_transition[$field_id]["100"][$value]['transition_id'];
02101 }
02102 }
02103
02104 }
02105 }
02106
02107 if (trackers_data_is_text_area($field) ||
02108 trackers_data_is_text_field($field))
02109 {
02110 $value = htmlspecialchars($value);
02111 }
02112 else if (trackers_data_is_date_field($field))
02113 {
02114 # if it's a date we must convert the format to unix time
02115 list($value,$ok) = utils_date_to_unixtime($value);
02116 }
02117
02118 $vfl_cols .= ','.$field;
02119 $vfl_values .= ',\''.$value.'\'';
02120
02121 # Keep track of the change:
02122 $changes[$field]['del']=
02123 trackers_field_display($field,$group_id,$old_value,false,false,true,true);
02124 $changes[$field]['add']=
02125 trackers_field_display($field,$group_id,$value,false,false,true,true);
02126
02127 # Register transition id
02128 $field_transition_accepted[] = $field_transition_id;
02129
02130
02131 if ($field_transition_cc)
02132 { $extra_addresses .= $field_transition_cc; }
02133 }
02134
02135 # Add all special fields that were not handled in the previous block
02136 $fixed_cols = 'close_date,group_id,submitted_by,date,summary,details';
02137 # FIXME: Make an exception for the cookbook, since it currently requires
02138 # HTML to be inserted. This is an ugly hack and should be fixed real soon.
02139 $sql_details = htmlspecialchars($vfl['details']);
02140 if (ARTIFACT == "cookbook")
02141 {
02142 # FIXME: This makes an XSS attack possible!
02143 $sql_details = $vfl['details'];
02144 }
02145 $fixed_values = "'0','$group_id','$user','".time()."','".
02146 htmlspecialchars($vfl['summary'])."','".$sql_details."'";
02147
02148
02149 $sql="INSERT INTO ".ARTIFACT." ($fixed_cols $vfl_cols) VALUES ($fixed_values $vfl_values)";
02150 $result=db_query($sql);
02151 $item_id=db_insertid($result);
02152
02153 if (!$item_id)
02154 {
02155 fb(_("New item insertion failed, please report this issue to the administrator"), 1);
02156 return false;
02157 }
02158
02159 $item = utils_get_tracker_prefix(ARTIFACT)." #".$item_id;;
02160 fb(sprintf(_("New item posted (%s)"), $item));
02161
02162 # If we are on the cookbook, Store related links
02163 if (ARTIFACT == 'cookbook')
02164 {
02165 cookbook_handle_update($item_id,$group_id);
02166 }
02167
02168 # Now we run transitions other fields update. This function does check
02169 # what already changed and that we wont automatically update
02170 trackers_transition_update_item($item_id, $field_transition_accepted, $changes);
02171
02172 #now return the trackers_id
02173 return $item_id;
02174 }
02175
02176 function trackers_data_get_value($field,$group_id,$value_id,$by_field_id=false)
02177 {
02178
02179
02180
02181
02182
02183
02184
02185
02186 # close_date and assigned_to fields are special select box fields
02187 if (($field == 'assigned_to') || ($field == 'submitted_by'))
02188 {
02189 return user_getname($value_id);
02190 }
02191 else if (trackers_data_is_date_field($field))
02192 {
02193 return format_date($sys_datefmt,$value_id);
02194 }
02195
02196 if ($by_field_id)
02197 {
02198 $field_id = $field;
02199 } else
02200 {
02201 $field_id = trackers_data_get_field_id($field);
02202 }
02203
02204 # Look for project specific values first...
02205 $sql="SELECT * FROM ".ARTIFACT."_field_value ".
02206 "WHERE bug_field_id='$field_id' AND group_id='$group_id' ".
02207 "AND value_id='$value_id'";
02208 $result=db_query($sql);
02209 if ($result && db_numrows($result) > 0)
02210 {
02211 return db_result($result,0,'value');
02212 }
02213
02214 # ... if it fails, look for system wide default values (group_id=100)...
02215 $sql="SELECT * FROM ".ARTIFACT."_field_value ".
02216 "WHERE bug_field_id='$field_id' AND group_id='100' ".
02217 "AND value_id='$value_id'";
02218 $result=db_query($sql);
02219 if ($result && db_numrows($result) > 0)
02220 {
02221 return db_result($result,0,'value');
02222 }
02223
02224 # No value found for this value id !!!
02225 return $value_id.'(Error - Not Found)';
02226
02227 }
02228
02229 function trackers_data_get_canned_responses ($group_id)
02230 {
02231
02232
02233
02234 $sql="SELECT bug_canned_id,title,body,order_id FROM ".ARTIFACT."_canned_responses WHERE ".
02235 "(group_id='$group_id' OR group_id='0') ORDER BY order_id ASC";
02236
02237 # return handle for use by select box
02238 return db_query($sql);
02239 }
02240
02241 function trackers_data_get_reports($group_id, $user_id=100, $sober=false)
02242 {
02243 # Currently, reports are group based.
02244 # Print first system reports.
02245
02246 # OUTDATED: currently personal query forms are deactivated in the code
02247 # If user is unknown then get only project-wide and system wide reports
02248 # else get personal reports in addition project-wide and system wide.
02249
02250 # We usually want non-sober specific query forms.
02251 $system_scope = 'S';
02252 if ($sober)
02253 {
02254 $system_scope = 'SSB';
02255 }
02256
02257 $sql = 'SELECT report_id,name FROM '.ARTIFACT.'_report WHERE ';
02258
02259 # if (!$user_id || ($user_id == 100))
02260 # {
02261
02262 $sql .= "(group_id=$group_id AND scope='P') OR scope='$system_scope' ORDER BY scope DESC , report_id ASC ";
02263
02264 # OUTDATED: currently personal query forms are deactivated in the code
02265 # } else
02266 # {
02267 # $sql .= "(group_id=$group_id AND (user_id=$user_id OR scope='P')) OR ".
02268 # "scope='S' ORDER BY scope,report_id";
02269 # }
02270 # print "DBG sql report = $sql";
02271
02272 return db_query($sql);
02273 }
02274
02275 function trackers_data_get_notification($user_id)
02276 {
02277 $sql = "SELECT role_id,event_id,notify FROM trackers_notification WHERE user_id='$user_id'";
02278 return db_query($sql);
02279 }
02280
02281 function trackers_data_get_notification_with_labels($user_id)
02282 {
02283 $sql = 'SELECT role_label,event_label,notify FROM trackers_notification_role, trackers_notification_event, trackers_notification '.
02284 "WHERE trackers_notification.role_id=trackers_notification_role.role_id AND trackers_notification.event_id=trackers_notification_event.event_id AND user_id='$user_id'";
02285 return db_query($sql);
02286 }
02287
02288 function trackers_data_get_notification_roles()
02289 {
02290 $sql = 'SELECT * FROM trackers_notification_role ORDER BY rank ASC;';
02291 return db_query($sql);
02292 }
02293
02294 function trackers_data_get_notification_events()
02295 {
02296 $sql = 'SELECT * FROM trackers_notification_event ORDER BY rank ASC;';
02297 return db_query($sql);
02298 }
02299
02300 function trackers_data_delete_notification($user_id)
02301 {
02302 $sql = "DELETE FROM trackers_notification WHERE user_id='$user_id'";
02303 return db_query($sql);
02304 }
02305
02306 function trackers_data_insert_notification($user_id, $arr_roles, $arr_events,$arr_notification)
02307 {
02308
02309 $sql = 'INSERT INTO trackers_notification (user_id,role_id,event_id,notify) VALUES ';
02310
02311 $num_roles = count($arr_roles);
02312 $num_events = count($arr_events);
02313 for ($i=0; $i<$num_roles; $i++)
02314 {
02315 $role_id = $arr_roles[$i]['role_id'];
02316 for ($j=0; $j<$num_events; $j++)
02317 {
02318 $event_id = $arr_events[$j]['event_id'];
02319 $sql .= "('$user_id','$role_id','$event_id','".$arr_notification[$role_id][$event_id]."'),";
02320 }
02321 }
02322 $sql = substr($sql,0,-1); # remove extra comma at the end
02323 return db_query($sql);
02324 }
02325
02326 function trackers_data_get_watchers($user_id)
02327 {
02328 $sql = "SELECT user_id,group_id FROM trackers_watcher WHERE watchee_id='$user_id'";
02329 return db_query($sql);
02330 }
02331
02332 function trackers_data_get_watchees($user_id)
02333 {
02334 $sql = "SELECT watchee_id,group_id FROM trackers_watcher WHERE user_id='$user_id'";
02335 return db_query($sql);
02336 }
02337
02338 function trackers_data_insert_watchees($user_id, $arr_watchees)
02339 {
02340 # No longer really used
02341 $sql = 'INSERT INTO trackers_watcher (user_id,watchee_id) VALUES ';
02342 $num_watchees = count($arr_watchees);
02343 for ($i=0; $i<$num_watchees; $i++)
02344 {
02345 $sql .= "('$user_id','".$arr_watchees[$i]."'),";
02346 }
02347 $sql = substr($sql,0,-1); # remove extra comma at the end
02348 return db_query($sql);
02349 }
02350
02351
02352 function trackers_data_add_watchees ($user_id, $watchee_id, $group_id)
02353 {
02354 if (member_check(0,$group_id) && !trackers_data_is_watched($user_id,$watchee_id,$group_id))
02355 {
02356 # Only accept the request from a member of the project
02357 # Note that a user can trick the URL to watch himself
02358 # It has no consequences, so we do not care.
02359 $sql = 'INSERT INTO trackers_watcher (user_id,watchee_id,group_id) VALUES '.
02360 "('$user_id','$watchee_id','$group_id')";
02361 return db_query($sql);
02362 }
02363 else
02364 {
02365 return 0;
02366 }
02367 }
02368
02369
02370 function trackers_data_delete_watchees ($user_id, $watchee_id, $group_id)
02371 {
02372 $sql = "DELETE FROM trackers_watcher WHERE user_id='$user_id' AND watchee_id='$watchee_id' AND group_id='$group_id'";
02373 return db_query($sql);
02374 }
02375
02376
02377 function trackers_data_is_watched ($user_id, $watchee_id, $group_id)
02378 {
02379 $sql = "SELECT watchee_id FROM trackers_watcher WHERE user_id='$user_id' AND watchee_id='$watchee_id' AND group_id='$group_id'";
02380 return db_result(db_query($sql),0,'watchee_id');
02381 }
02382
02383
02384 function trackers_data_delete_file($group_id, $item_id, $item_file_id)
02385 {
02386 # Make sure the attachment belongs to the group
02387 $res = db_query("SELECT bug_id from ".ARTIFACT." WHERE bug_id=$item_id AND group_id=$group_id");
02388 if (db_numrows($res) <= 0)
02389 {
02390 sprintf(_("Item #%s doesn't belong to project"), $item_id);
02391 return;
02392 }
02393
02394 # Now delete the attachment
02395 $result = db_query("DELETE FROM trackers_file WHERE item_id='$item_id' AND file_id='$item_file_id'");
02396 if (!$result)
02397 {
02398 "Error deleting attachment #$item_file_id: ".db_error($res);
02399 }
02400 else
02401 {
02402 fb(_("File successfully deleted"));
02403 trackers_data_add_history("Attached File",
02404 "#".$item_file_id,
02405 "Removed",
02406 $item_id,
02407 0,0,1);
02408 }
02409
02410 }
02411
02412
02413
02414 function trackers_data_count_field_value_usage ($group_id, $field, $field_value_value_id)
02415 {
02416 return db_numrows(db_query("SELECT bug_id FROM ".ARTIFACT." WHERE $field='$field_value_value_id' AND group_id='$group_id'"));
02417 }
02418
02419 ?>