Main Page | Directories | File List | File Members

data.php

Go to the documentation of this file.
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 Simple way of wrapping our SQL so it can be
00032         shared among the XML outputs and the PHP web front-end
00033 
00034         Also abstracts controls to update data
00035 
00036 */
00037 function trackers_data_get_all_fields ($group_id=false,$reload=false)
00038 {
00039 
00040   /*
00041            Get all the possible bug fields for this project both used and unused. If
00042            used then show the project specific information about field usage
00043            otherwise show the default usage parameter
00044            Make sure array element are sorted by ascending place
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.' />&nbsp;&nbsp;<span class="preinput">'._("Notify persons in the global list only").'</span><br />
00192           <INPUT TYPE="RADIO" NAME="'.$tracker_name.'_notif_scope" VALUE="category" '.$categoryradio.' />&nbsp;&nbsp;<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.' />&nbsp;&nbsp;<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 />&nbsp;&nbsp;<INPUT TYPE="TEXT" NAME="'.$tracker_name.'_cat_'.$i.'_email" VALUE="'.$grtrsettings['category'][$i]['email'].'" SIZE="50" MAXLENGTH="255" />
00203           &nbsp;&nbsp;<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 />&nbsp;&nbsp;<INPUT TYPE="TEXT" NAME="'.$tracker_name.'_new_item_address" VALUE="'.$grtrsettings['glnewad'].'" SIZE="50" MAXLENGTH="255" />
00216       &nbsp;&nbsp;<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 />&nbsp;&nbsp;<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            Get all the bug fields involved in the bug report.
00393            WARNING: This function ust only be called after bug_init()
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              Return all possible values for a select box field
00426              Rk: if the checked value is given then it means that we want this value
00427                   in the list in any case (even if it is hidden and active_only is requested)
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       Return the default value associated to a field_name as defined in the
00811       bug table (SQL definition)
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       Find the maximum value for the value_id of a field for a given group
00828       Return -1 if  no value exist yet
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       Return true if there is an existing set of values for given field for a
00858       given group and false if it is empty
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       Initialize the set of values for a given field for a given group by using
00878       the system default (default values belong to group_id 'None' =100)
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       Get all the columns associated to a given field value
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       See if this field value belongs to group None (100). In this case
00966       it is a so called default value.
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       Insert a new value for a given field for a given group
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       Insert a new value for a given field for a given group
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       Reset a field settings to its defaults usage (values are untouched). The defaults
01096       always belong to group_id 100 (None) so make sure we don;t delete entries for
01097       group 100
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       Update a field settings in the trackers_usage_table
01127       Rk: All the show_on_xxx boolean parameters are set to 0 by default because their
01128            values come from checkboxes and if not checked the form variable
01129            is not set at all. It must be 0 to be ok with the SQL statement
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                 Get the items for this project
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                 Get the list of ids this is dependent on
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       simply return the value associated with a given value_id
02180       for a given field of a given group. If associated value not
02181       found then return value_id itself.
02182       By doing so if this function is called by mistake on a field with type
02183       text area or text field then it returns the text itself.
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       Show defined and site-wide responses
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 ?>

Generated on Sun Feb 26 13:23:03 2006 for Savane PHP Frontend Developer Reference by  doxygen 1.4.4