Main Page | Directories | File List | File Members

trackers/general.php File Reference

Go to the source code of this file.

Functions

 trackers_include ()


Function Documentation

trackers_include  ) 
 

Definition at line 31 of file trackers/general.php.

00032 {
00033   # Keep the dirname only if it's admin
00034   $dir = get_module_include_dir($GLOBALS['PHP_SELF'], 0, 1);
00035   if ($dir != "admin")
00036     {
00037       unset($dir);
00038     }
00039   else
00040     {
00041       $dir = $dir."/";
00042       $pre = "../";
00043     }
00044 
00045   return $pre."../include/trackers_run/".$dir.basename($GLOBALS['PHP_SELF']);
00046 }
00047 
00048 # Does like trackers_include() but load an arbitrary page of the common
00049 # tracker code. This is useful for trackers that have non-standard behavior
00050 # needs to present some standard page inside a non standard location
00051 function trackers_bastardinclude($page, $is_admin_page='0')
00052 {
00053   unset($pre);
00054   if ($is_admin_page)
00055     {
00056       $pre = "../";
00057     }
00058 
00059   return $pre."../include/trackers_run/".$page.".php";
00060 }
00061 
00062 
00063 # Generate URL arguments from a variable wether scalar or array
00064 function trackers_convert_to_url_arg($varname, $var)
00065 {
00066 
00067   if (is_array($var))
00068     {
00069       reset($var);
00070       while (list(,$v) = each($var))
00071         {
00072           $ret .= '&'.$varname.'[]='.$v;
00073         }
00074     }
00075   else
00076     {
00077       $ret .= '&'.$varname.'='.$var;
00078     }
00079   return $ret;
00080 }
00081 
00082 function trackers_header($params)
00083 {
00084   global $group_id,$is_bug_page,$DOCUMENT_ROOT,$advsrch;
00085 
00086   #used so the search box will add the necessary element to the pop-up box
00087   # yeupou, 2005-09-11: is that still useful?
00088   $is_bug_page=1;
00089 
00090   #required params for site_project_header();
00091   $params['group']=$group_id;
00092   $params['context']=ARTIFACT;
00093 
00094   $project=project_get_object($group_id);
00095 
00096   #needs to be turned  on
00097   if (ARTIFACT == "bugs"  && !$project->Uses("bugs") ||
00098       ARTIFACT == "support" &&  !$project->Uses("support") ||
00099       ARTIFACT == "task" && !$project->Uses("task") ||
00100       ARTIFACT == "patch" && !$project->Uses("patch"))
00101     {
00102       exit_error(_("This project has turned off this tracker."));
00103     }
00104   print site_project_header($params);
00105 
00106 }
00107 
00108 function trackers_header_admin($params)
00109 {
00110   global $group_id,$is_bug_page,$DOCUMENT_ROOT;
00111 
00112   #used so the search box will add the necessary element to the pop-up box
00113   $is_bug_page=1;
00114 
00115   #required params for site_project_header();
00116   $params['group']=$group_id;
00117   $params['context']='a'.ARTIFACT;
00118 
00119   $project=project_get_object($group_id);
00120 
00121   # need to be turned on
00122   if (ARTIFACT == "bugs"  && !$project->Uses("bugs") ||
00123       ARTIFACT == "support" &&  !$project->Uses("support") ||
00124       ARTIFACT == "task" && !$project->Uses("task") ||
00125       ARTIFACT == "patch" && !$project->Uses("patch"))
00126     {
00127       exit_error(_("This project has turned off this tracker."));
00128     }
00129   print site_project_header($params);
00130 }
00131 
00132 function trackers_footer($params)
00133 {
00134   site_project_footer($params);
00135 }
00136 
00137 function trackers_init($group_id)
00138 {
00139   # Set the global arrays for faster processing at init time
00140   trackers_data_get_all_fields($group_id, true);
00141 }
00142 
00143 function trackers_report_init($group_id, $report_id)
00144 {
00145   # Set the global array with report information for faster processing
00146   trackers_data_get_all_report_fields($group_id, $report_id, true);
00147 }
00148 
00149 function trackers_list_all_fields($sort_func=false,$by_field_id=false)
00150 {
00151   global $BF_USAGE_BY_ID, $BF_USAGE_BY_NAME, $AT_START;
00152 
00153   # If its the first element we fetch then apply the sort
00154   # function
00155   if ($AT_START)
00156     {
00157       if (!$sort_func)
00158         { $sort_func = cmp_place; }
00159       uasort($BF_USAGE_BY_ID, $sort_func);
00160       uasort($BF_USAGE_BY_NAME, $sort_func);
00161       $AT_START=false;
00162     }
00163 
00164   # return the next bug field in the list. If the global
00165   # bug field usage array is not set then set it the
00166   # first time.
00167   # by_field_id: true return the list of field id, false returns the
00168   # list of field names
00169 
00170   if ( list($key, $field_array) = each($BF_USAGE_BY_ID))
00171     {
00172       return($by_field_id ? $field_array['bug_field_id'] : $field_array['field_name']);
00173     }
00174   else
00175     {
00176       # rewind internal pointer for next time
00177       reset($BF_USAGE_BY_ID);
00178       reset($BF_USAGE_BY_NAME);
00179       $AT_START=true;
00180       return(false);
00181     }
00182 }
00183 
00184 function trackers_field_label_display ($field_name, $group_id,$break=false,$ascii=false, $tab=25)
00185 {
00186   $label = trackers_data_get_label($field_name).':';
00187 
00188   if (!$ascii)
00189     { $output = '<span class="preinput"><span class="help" title="'.trackers_data_get_description($field_name).'">'.$label.'</span></span>'; }
00190 
00191   if ($break)
00192     { $output .= ($ascii?"\n":'<br />'); }
00193   else
00194     {
00195       if (!$ascii)
00196         { $output .= '&nbsp;'; }
00197       else
00198         {
00199           $output .= sprintf("%".$tab."s", $label).' ';
00200         }
00201      }
00202 
00203   return $output;
00204 }
00205 
00206 function trackers_field_display ($field_name,
00207                                  $group_id,
00208                                  $value='xyxy',
00209                                  $break=false, #4
00210                                  $label=true,
00211                                  $ro=false, #6
00212                                  $ascii=false,
00213                                  $show_none=false, #8
00214                                  $text_none='None',
00215                                  $show_any=false, #10
00216                                  $text_any='Any',
00217                                  $allowed_transition_only=false, #12
00218                                  $show_unknown=false,
00219                                  $tab=25)
00220 {
00221   /*
00222           Display a bug field either as a read-only value or as a read-write
00223           making modification possible
00224           - field_name : name of the bug field (column name)
00225           - group_id : the group id (project id)
00226           - value: the current value stored in this field (for select boxes type of field
00227                   it is the value_id actually. It can also be an array with mutliple values.
00228           - break: true if a break line is to be inserted between the field label
00229                  and the field value
00230           - label: if true display the field label.
00231           - ro: true if only the field value is to be displayed. Otherwise
00232                  display an HTML select box, text field or text area to modify the value
00233           - ascii: if true do not use any HTML decoration just plain text (if true
00234                  then read-only (ro) flag is forced to true as well)
00235           - show_none: show the None entry in the select box if true (value_id 100)
00236           - text_none: text associated with the none value_id to display in the select box
00237           - show_any: show the Any entry in the select box if true (value_id 0)
00238           - text_any: text associated with the any value_id  tp display in the select box
00239           - allowed_transition_only: print only transition allowed
00240   */
00241 
00242   global $sys_datefmt;
00243 
00244   if ($label)
00245     {
00246       $output = trackers_field_label_display($field_name,
00247                                              $group_id,
00248                                              $break,
00249                                              $ascii,
00250                                              $tab);
00251     }
00252 
00253   # display depends upon display type of this field
00254   switch (trackers_data_get_display_type($field_name))
00255     {
00256 
00257     case 'SB':
00258       if ($ro)
00259         {
00260 
00261           # if multiple selected values return a list of <br /> separated values
00262           $arr = ( is_array($value) ? $value : array($value));
00263           for ($i=0;$i < count($arr); $i++)
00264             {
00265               if ($arr[$i] == 0 )
00266                 { $arr[$i] = $text_any; }
00267               else if ($arr[$i] == 100 && $field_name != 'percent_complete')
00268                 { $arr[$i] = $text_none; }
00269               else
00270                 { $arr[$i] = trackers_data_get_value($field_name,$group_id,$arr[$i]); }
00271             }
00272           $output .= join('<br />', $arr);
00273 
00274         }
00275       else
00276         {
00277           # If it is a user name field (assigned_to, submitted_by) then make
00278           # sure to add the "None" entry in the menu 'coz it's not in the DB
00279           if (trackers_data_is_username_field($field_name))
00280             {
00281               $show_none=true;
00282               $text_none='None';
00283             }
00284 
00285           if (is_array($value))
00286             {
00287               $output .= trackers_multiple_field_box($field_name,'',$group_id, $value,
00288                                                      $show_none,$text_none,$show_any,
00289                                                      $text_any);
00290             }
00291           else
00292             {
00293               $output .= trackers_field_box($field_name,
00294                                             '',
00295                                             $group_id,
00296                                             $value, #4
00297                                             $show_none,
00298                                             $text_none,
00299                                             $show_any,
00300                                             $text_any, #8
00301                                             $allowed_transition_only,
00302                                             $show_unknown);
00303             }
00304         }
00305       break;
00306 
00307     case 'DF':
00308       if ($ascii)
00309         {
00310           $output .= ( ($value == 0) ? '' : format_date($sys_datefmt,$value));
00311         }
00312       else
00313         {
00314           if ($ro)
00315             { $output .= format_date($sys_datefmt,$value); }
00316         else
00317           {
00318             $output .= trackers_field_date($field_name,
00319                                            (($value == 0) ? '' : strftime("%Y-%m-%d",$value)));
00320           }
00321         }
00322       break;
00323 
00324     case 'TF':
00325       if ($ascii)
00326         { $output .= utils_unconvert_htmlspecialchars($value); }
00327       else
00328         { $output .= ($ro ? $value: trackers_field_text($field_name,$value)); }
00329       break;
00330 
00331     case 'TA':
00332       if ($ascii)
00333         { $output .= utils_unconvert_htmlspecialchars($value); }
00334       else
00335         { $output .= ($ro ? nl2br($value):trackers_field_textarea($field_name,$value)); }
00336       break;
00337 
00338     default:
00339       $output .= 'Unknown '.ARTIFACT.' Field Display Type';
00340     }
00341 
00342   return($output);
00343 }
00344 
00345 function trackers_field_date($field_name,$value='',$size=0,$maxlength=0,$ro=false)
00346 {
00347 
00348   # value is formatted as Y-m-d
00349   list($year, $month, $day) = split("-", $value);
00350 
00351   if ($ro)
00352     {
00353       $html = $value;
00354     }
00355   else
00356     {
00357       if (!$size || !$maxlength)
00358         { list($size, $maxlength) = trackers_data_get_display_size($field_name);
00359     }
00360 
00361       # date part are missing, take the date of the day
00362       $today = localtime();
00363       if (!$day)
00364         { $day = ($today[3]); }
00365       if (!$month)
00366         { $month = ($today[4]+1); }
00367       if (!$year)
00368         { $year = ($today[5]+1900); }
00369 
00370       # FIXME: order of year/day/month must be local specific
00371       $html = calendar_selectbox("day", $day, $field_name.'_dayfd').calendar_selectbox("month", $month, $field_name.'_monthfd').' <input type="text" name="'.$field_name.'_yearfd" size="4" maxlength="4" value="'.$year.'" />';
00372     }
00373   return($html);
00374 
00375 }
00376 
00377 function trackers_multiple_field_date($field_name,$date_begin='',$date_end='',$size=0,$maxlength=0,$ro=false)
00378 {
00379 
00380   # CAUTION!!!! The Javascript below assumes that the date always appear
00381   # in a field called 'bug_form'
00382 
00383   # FIXME: this is broken, should be made as trackers_field_date
00384 
00385   if ($ro)
00386     if ($date_begin || $date_end)
00387       $html = "Start:&nbsp;$date_begin<br />End:&nbsp;$date_end";
00388     else
00389       $html = 'Any time';
00390   else
00391     {
00392       if (!$size || !$maxlength)
00393         list($size, $maxlength) = trackers_data_get_display_size($field_name);
00394 
00395       $html = 'Start:<br /><input type="text" name="'.$field_name.
00396          '" size="'.$size.'" MAXLENGTH="'.$maxlength.'" VALUE="'.$date_begin.'">'.
00397          '<a href="javascript:show_calendar(\'document.bug_form.'.$field_name.'\', document.bug_form.'.$field_name.'.value);">'.
00398          '<img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/task.png" border="0" alt="'._("Click Here to Pick up a date").'" /></a>'.
00399          '</td></tr><tr><td>'.
00400          'End:<br /><INPUT TYPE="text" name="'.$field_name.'_end'.
00401          '" size="'.$size.'" MAXLENGTH="'.$maxlength.'" VALUE="'.$date_end.'">'.
00402          '<a href="javascript:show_calendar(\'document.bug_form.'.$field_name.'_end\', document.bug_form.'.$field_name.'_end.value);">'.
00403          '<img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/task.png" border="0" alt="'._("Click Here to Pick up a date").'" /></a>';
00404 
00405       $html = '<table><tr><td>'.$html.'</td></tr></table>';
00406     }
00407 
00408   return($html);
00409 
00410 }
00411 
00412 function trackers_field_date_operator($field_name,$value='',$ro=false)
00413 {
00414 
00415   if ($ro)
00416     $html = htmlspecialchars($value);
00417   else
00418     $html = '<SELECT name="'.$field_name.'_op">'.
00419       '<OPTION VALUE=">"'.(($value == '>') ? ' SELECTED':'').'>&gt;</OPTION>'.
00420       '<OPTION VALUE="="'.(($value == '=') ? ' SELECTED':'').'>=</OPTION>'.
00421       '<OPTION VALUE="<"'.(($value == '<') ? ' SELECTED':'').'>&lt;</OPTION>'.
00422       '</SELECT>';
00423   return($html);
00424 
00425 }
00426 
00427 function trackers_field_text($field_name,$value='',$size=0,$maxlength=0)
00428 {
00429 
00430   if (!$size || !$maxlength)
00431     list($size, $maxlength) = trackers_data_get_display_size($field_name);
00432 
00433   $html = '<input type="text" name="'.$field_name.
00434      '" size="'.$size.'" maxlength="'.$maxlength.'" value="'.$value.'" />';
00435   return($html);
00436 
00437 }
00438 
00439 function trackers_field_textarea($field_name,$value='',$cols=0,$rows=0)
00440 {
00441 
00442   if (!$cols || !$rows)
00443     {
00444       list($cols, $rows) = trackers_data_get_display_size($field_name);
00445 
00446       # Nothing defined for this field? Use hardcoded default values
00447       if (!$cols || !$rows)
00448         {
00449           $cols = "65";
00450           $rows = "16";
00451         }
00452     }
00453 
00454   $html = '<textarea name="'.$field_name.
00455      '" rows="'.$rows.'" cols="'.$cols.'" wrap="soft">'.$value.'</textarea>';
00456   return($html);
00457 
00458 }
00459 
00460 function trackers_field_box ($field_name,
00461                              $box_name='',
00462                              $group_id,
00463                              $checked=false, #4
00464                              $show_none=false,
00465                              $text_none='None',
00466                              $show_any=false,
00467                              $text_any='Any', #8
00468                              $allowed_transition_only=false,
00469                              $show_unknown=false)
00470 {
00471 
00472   # Returns a select box populated with field values for this project
00473   # if box_name is given then impose this name in the select box
00474   # of the  HTML form otherwise use the field_name
00475   if (!$group_id)
00476     { return _('Error: no group defined'); }
00477   else
00478     {
00479       $result = trackers_data_get_field_predefined_values($field_name,$group_id,$checked);
00480 
00481       if ($box_name == '')
00482         { $box_name = $field_name; }
00483 
00484       if ($allowed_transition_only)
00485         {
00486           # yeupou--gnu.org 2004-09-12: where the hell is by_field_id set?
00487           $field_id = ($by_field_id ? $field_name : trackers_data_get_field_id($field_name));
00488 
00489           # first check if group has defined transitions for this field
00490           $default_auth = db_result(db_query("SELECT transition_default_auth ".
00491                                              "FROM ".ARTIFACT."_field_usage ".
00492                                              "WHERE group_id='$group_id' AND bug_field_id='$field_id'"), 0, 'transition_default_auth');
00493           # avoid corrupted database content, if its not F, it must be A.
00494           if ($default_auth != "F")
00495             { $default_auth = "A"; }
00496 
00497           $sql="SELECT from_value_id,to_value_id,is_allowed,notification_list ".
00498              "FROM trackers_field_transition ".
00499              "WHERE group_id='$group_id' AND artifact='".ARTIFACT."' AND field_id='$field_id' AND (from_value_id='$checked' OR from_value_id='0')";
00500 
00501           $trans_result = db_query($sql);
00502           $forbidden_to_id = array();
00503           $allowed_to_id = array();
00504           $rows = db_numrows($trans_result);
00505           if ($trans_result && $rows > 0 || $default_auth == "F")
00506             {
00507               while ($transition = db_fetch_array($trans_result))
00508                 {
00509                   if ($transition['is_allowed'] == 'F')
00510                     {
00511                       $forbidden_to_id[$transition['to_value_id']] = 0;
00512                     }
00513                   else
00514                     {
00515                       $allowed_to_id[$transition['to_value_id']] = 0;
00516                     }
00517                 }
00518 
00519               # get all the predefined values for this field
00520               $rows=db_numrows($result);
00521 
00522               if ($rows > 0) {
00523                 $val_label = array();
00524                 while ($val_row = db_fetch_array($result))
00525                   {
00526                     $value_id = $val_row['value_id'];
00527                     $value   = $val_row['value'];
00528                     if ((($default_auth == 'A') && (!array_key_exists($value_id, $forbidden_to_id))) ||
00529                         (($default_auth == 'F') && (array_key_exists($value_id, $allowed_to_id))) ||
00530                         ($value_id == $checked))
00531                       {
00532                         $val_label[$value_id] = $value;
00533                       }
00534                   }
00535 
00536                 # always add the any values cases
00537                 return html_build_select_box_from_arrays(array_keys($val_label),
00538                                                          array_values($val_label),
00539                                                          $box_name,
00540                                                          $checked, #4
00541                                                          $show_none,
00542                                                          $text_none, #6
00543                                                          $show_any,
00544                                                          $text_any, #8
00545                                                          $show_unknown);
00546           }
00547         }
00548       }
00549 
00550 # if no transition defined use 'normal' code
00551 
00552       return html_build_select_box ($result,$box_name,$checked,$show_none,$text_none,$show_any, $text_any,$show_unknown);
00553 
00554     }
00555 }
00556 
00557 function trackers_multiple_field_box($field_name,
00558                                      $box_name='',
00559                                      $group_id,
00560                                      $checked=false,
00561                                      $show_none=false,
00562                                      $text_none='None',
00563                                      $show_any=false,
00564                                      $text_any='Any',
00565                                      $show_value=false)
00566 {
00567   # Returns a multiplt select box populated with field values for this project
00568   # if box_name is given then impose this name in the select box
00569   # of the  HTML form otherwise use the field_name
00570 
00571   if (!$group_id)
00572     { return _("Internal error: no group id"); }
00573   else
00574     {
00575       $result = trackers_data_get_field_predefined_values($field_name,$group_id,$checked);
00576 
00577       if ($box_name == '')
00578         {
00579           $box_name = $field_name.'[]';
00580         }
00581       return html_build_multiple_select_box($result,$box_name,$checked,6,$show_none,$text_none, $show_any,$text_any,$show_value);
00582     }
00583 }
00584 
00585 # Similar to trackers_multiple_field_box except that it will use checkboxes
00586 # instead of a multiple select field. Multiple select field is nice for
00587 # expert users, but it is not simple user-friendly, unlike checkboxes.
00588 function trackers_multiple_field_box2 ($field_name,
00589                                        $box_name='',
00590                                        $group_id,
00591                                        $checked=false,
00592                                        $show_none=false,
00593                                        $text_none='None',
00594                                        $show_any=false,
00595                                        $text_any='Any',
00596                                        $show_value=false)
00597 {
00598   if (!$group_id)
00599     { return _("Internal error: no group id"); }
00600   else
00601     {
00602       $result = trackers_data_get_field_predefined_values($field_name,$group_id,$checked);
00603 
00604       if ($box_name == '')
00605         {
00606           $box_name = $field_name.'[]';
00607         }
00608       return html_build_checkbox($result,$box_name,$checked,6,$show_none,$text_none, $show_any,$text_any,$show_value);
00609     }
00610 
00611 
00612 }
00613 
00614 function trackers_extract_field_list($post_method=true)
00615 {
00616 
00617   global $HTTP_GET_VARS, $HTTP_POST_VARS, $BF_USAGE_BY_NAME;
00618   /*
00619        Returns the list of field names in the HTML Form corresponding to a
00620        field used by this project
00621   */
00622 
00623   # Specific: it must build the date fields if it finds _dayfd, _monthfd
00624   # or _yearfd, because date fields comes from 3 separated input.
00625   $vfl = array();
00626   $date = array();
00627   if ($post_method)
00628     {
00629       reset($HTTP_POST_VARS);
00630       while ( list($key, $val) = each($HTTP_POST_VARS))
00631         {
00632           if (preg_match("/^(.*)_(day|month|year)fd$/", $key, $found))
00633             {
00634               # Must build the date field key.
00635               $field_name = $found[1];
00636               $field_name_part = $found[2];
00637 
00638               # We also must increment $day and $month, because the select
00639               # start from zero
00640 
00641               # get what we already have
00642               list($year, $month, $day) = split("-", $vfl[$field_name]);
00643               if ($field_name_part  == 'day')
00644                 { $vfl[$field_name] = "$year-$month-$val"; }
00645               elseif ($field_name_part == 'month')
00646                 { $vfl[$field_name] = "$year-$val-$day"; }
00647               elseif ($field_name_part == 'year')
00648                 { $vfl[$field_name] = "$val-$month-$day"; }
00649             }
00650           elseif (isset($BF_USAGE_BY_NAME[$key]) || $key == 'comment')
00651             {
00652               $vfl[$key] = $val;
00653             }
00654           else
00655             {
00656               dbg("Rejected key = ".$key." val = $val");
00657             }
00658         }
00659     }
00660   else
00661     {
00662       reset($HTTP_GET_VARS);
00663       while ( list($key, $val) = each($HTTP_GET_VARS))
00664         {
00665           if (preg_match("/^(.*)_(day|month|year)fd$/", $key, $found))
00666             {
00667               # Must build the date field key.
00668               $field_name = $found[1];
00669               $field_name_part = $found[2];
00670 
00671               # get what we already have
00672               list($year, $month, $day) = split("-", $vfl[$field_name]);
00673               if ($field_name_part  == 'day')
00674                 { $vfl[$field_name] = "$year-$month-$val"; }
00675               elseif ($field_name_part == 'month')
00676                 { $vfl[$field_name] = "$year-$val-$day"; }
00677               elseif ($field_name_part == 'year')
00678                 { $vfl[$field_name] = "$val-$month-$day"; }
00679             }
00680           elseif (isset($BF_USAGE_BY_NAME[$key]) || $key == 'comment')
00681             {
00682               $vfl[$key] = $val;
00683             }
00684           else
00685             {
00686               dbg("Rejected key = ".$key." val = $val");
00687             }
00688         }
00689 
00690     }
00691   return($vfl);
00692 }
00693 
00694 # Check whether a field was shown to the submitter
00695 # (useful if a field is mandatory if shown to the submitter)
00696 function trackers_check_is_shown_to_submitter ($field_name, $group_id, $submitter_id)
00697 {
00698   if ($submitter_id == 100)
00699     {
00700       # Anonymous user
00701       if (trackers_data_is_showed_on_add_nologin($field_name))
00702         { return true; }
00703     }
00704   else
00705     {
00706       if (!member_check($submitter_id, $group_id))
00707         {
00708           # Not a member of the group
00709           if (trackers_data_is_showed_on_add($field_name))
00710             { return true; }
00711         }
00712       else
00713         {
00714           # Group member
00715           if (trackers_data_is_showed_on_add_members($field_name))
00716             { return true; }
00717         }
00718     }
00719 
00720   # if we reach this point, it was not mandatory
00721   return false;
00722 }
00723 
00724 
00725 function trackers_check_empty_fields($field_array, $new_item=true)
00726 {
00727   # Check whether empty values are allowed for the bug fields
00728   # field_array: associative array of field_name -> value
00729   unset($previous_form_bad_fields);
00730   global $previous_form_bad_fields;
00731   $previous_form_bad_fields = array();
00732 
00733 
00734   reset($field_array);
00735   while (list($field_name, $val) = each($field_array))
00736     {
00737       # Only the field percent_complete is allowed to use the special value
00738       # hundred.
00739       # FIXME: maybe it should not use that value at all, however it would
00740       # require one more database migration. Something that should indeed be
00741       # done if at some point we feel the need for one more exception.
00742       if ($field_name == "percent_complete")
00743         { continue; }
00744 
00745       # Check if it is empty
00746       $is_empty = (trackers_data_is_select_box($field_name) ? ($val==100) : ($val==''));
00747       if (!$is_empty)
00748         { continue; }
00749 
00750       # Check if it is mandatory
00751       $mandatory_flag = trackers_data_mandatory_flag($field_name);
00752       unset($is_mandatory);
00753       if ($mandatory_flag == 1)
00754         {
00755           # Not mandatory
00756           continue;
00757         }
00758       elseif ($mandatory_flag == 3)
00759         {
00760           # Mandatory whenever possible
00761           $is_mandatory = 1;
00762         }
00763       elseif ($new_item)
00764         {
00765           # Mandatory when shown to the submitter while we are creating
00766           # a new item.
00767           # ($mandatory_flag = 0)
00768           $is_mandatory = 1;
00769         }
00770       else
00771         {
00772           # Mandatory when shown to the submitter, we are updating an item
00773           # ($mandatory_flag = 0)
00774 
00775           global $item_id, $group_id, $mandatorycheck_submitter_id;
00776           if (!$mandatorycheck_submitter_id)
00777             {
00778               # Save that information for further mandatory checks,
00779               # to avoid avoid a SQL request per field checked
00780               $submitter_sql = "SELECT submitted_by FROM ".ARTIFACT." WHERE bug_id='$item_id' AND group_id='$group_id'";
00781               $submitter_res = db_query($submitter_sql);
00782               $mandatorycheck_submitter_id = db_result($submitter_res,0,'submitted_by');
00783             }
00784 
00785           if (trackers_check_is_shown_to_submitter($field_name, $group_id, $mandatorycheck_submitter_id))
00786             {
00787               $is_mandatory = 1;
00788             }
00789         }
00790 
00791       if ($is_mandatory)
00792         {
00793           $value = trackers_data_get_label($field_name);
00794           $previous_form_bad_fields[$field_name] = $value;
00795         }
00796     }
00797 
00798   if (count($previous_form_bad_fields) > 0)
00799     {
00800       # If not_new_item is true, it mean that there was no previous value to
00801       # reset the entry.
00802       if ($new_item)
00803         {
00804           fb(sprintf(ngettext("The field '%s' is mandatory. Fill it and re-submit the form.","The fields '%s' are mandatory. Fill them and re-submit the form.", count($previous_form_bad_fields)), join(', ',$previous_form_bad_fields)), 1);
00805         }
00806       else
00807         {
00808           fb(sprintf(ngettext("The field '%s' is mandatory. It has been reset to its previous value. Check it and re-submit the form.","The fields '%s' are mandatory. They have been reset to their previous value. Check them and re-submit the form.", count($previous_form_bad_fields)), join(', ',$previous_form_bad_fields)), 1);
00809         }
00810 
00811       return false;
00812     }
00813   else
00814     {
00815       return true;
00816     }
00817 
00818 }
00819 
00820 function trackers_canned_response_box ($group_id,$name='canned_response')
00821 {
00822   if (!$group_id)
00823     {
00824       fb(_("Error, no group_id"),1);
00825       return 0;
00826     }
00827   else
00828     {
00829       $vals = array();
00830       $texts = array();
00831       $result = trackers_data_get_canned_responses($group_id);
00832       if (db_numrows($result) > 0)
00833         {
00834           if (db_numrows($result) > 1)
00835             {
00836               $vals[] = '!multiple!';
00837               $texts[] = "> "._("Multiple Canned Responses");
00838             }
00839 
00840           while ($entry = db_fetch_array($result))
00841             {
00842               $vals[] = $entry['bug_canned_id'];
00843               $texts[] = $entry['title'];
00844 
00845             }
00846 
00847           return html_build_select_box_from_arrays($vals, $texts ,$name);
00848         }
00849       else
00850         {
00851           return form_input("hidden", "canned_response", "100")._("No canned response available");
00852         }
00853     }
00854 }
00855 
00856 function trackers_build_notification_matrix($user_id)
00857 {
00858   # Build the notif matrix indexed with roles and events labels (not id)
00859   $res_notif = trackers_data_get_notification_with_labels($user_id);
00860   while ($arr = db_fetch_array($res_notif))
00861     {
00862       $arr_notif[$arr['role_label']][$arr['event_label']] = $arr['notify'];
00863     }
00864   return $arr_notif;
00865 }
00866 
00867 
00868 function trackers_check_notification($user_id, $role, $changes=false)
00869 {
00870 
00871   $send = false;
00872   $arr_notif = trackers_build_notification_matrix($user_id);
00873   if (!$arr_notif)
00874     { return true; }
00875 
00876   #echo "==== DBG Checking Notif. for $user_id (role=$role)<br />";
00877   $user_name = user_getname($user_id);
00878 
00879   #----------------------------------------------------------
00880   # If it's a new bug only (changes is false) check the NEW_ITEM event and
00881   # ignore all other events
00882   if ($changes==false)
00883     {
00884       if ($arr_notif[$role]['NEW_ITEM'])
00885         {
00886           #echo "DBG NEW_ITEM notified<br />";
00887           return true;
00888         }
00889       else
00890         {
00891           #echo "DBG No notification<br />";
00892           return false;
00893         }
00894     }
00895 
00896   #----------------------------------------------------------
00897   #Check: I_MADE_IT  (I am the author of the change )
00898   # Check this one first because if the user said no she doesn't want to be
00899   # aware of any of her change in this role and we can return immediately.
00900   if (($user_id == user_getid()) && !$arr_notif[$role]['I_MADE_IT'])
00901     {
00902       #echo "DBG Dont want to receive my own changes<br />";
00903       return false;
00904     }
00905 
00906   #----------------------------------------------------------
00907   # Check :  NEW_COMMENT  A new followup comment is added
00908   if ($arr_notif[$role]['NEW_COMMENT'] && isset($changes['details']))
00909     {
00910       #echo "DBG NEW_COMMENT notified<br />";
00911       return true;
00912     }
00913 
00914   #----------------------------------------------------------
00915   #Check: NEW_FILE  (A new file attachment is added)
00916   if ($arr_notif[$role]['NEW_FILE'] && isset($changes['attach']))
00917     {
00918       #echo "DBG NEW_FILE notified<br />";
00919       return true;
00920     }
00921 
00922   #----------------------------------------------------------
00923   #Check: CLOSED  (The bug is closed)
00924   # Rk: this one has precedence over PSS_CHANGE. So notify even if PSS_CHANGE
00925   # says no.
00926   if ($arr_notif[$role]['CLOSED'] && ($changes['status_id']['add'] == 'Closed'))
00927     {
00928       #echo "DBG CLOSED bug notified<br />";
00929       return true;
00930     }
00931 
00932   #----------------------------------------------------------
00933   #Check: PSS_CHANGE  (Priority,Status,Severity changes)
00934   if ($arr_notif[$role]['PSS_CHANGE'] &&
00935       (isset($changes['priority']) || isset($changes['status_id']) || isset($changes['severity'])) )
00936     {
00937       #echo "DBG PSS_CHANGE notified<br />";
00938       return true;
00939     }
00940 
00941 
00942   #----------------------------------------------------------
00943   # Check :  ROLE_CHANGE (I'm added to or removed from this role)
00944   # Rk: This event is meanningless for Commenters. It also is for submitter but may be
00945   # one day the submitter will be changeable by the project admin so test it.
00946   # Rk #2: check this one at the end because it is the most CPU intensive and this
00947   # event seldomly happens
00948   if ($arr_notif['SUBMITTER']['ROLE_CHANGE'] &&
00949       (($changes['submitted_by']['add'] == $user_name) || ($changes['submitted_by']['del'] == $user_name)) &&
00950       ($role == 'SUBMITTER') )
00951     {
00952       #echo "DBG ROLE_CHANGE for submitter notified<br />";
00953       return true;
00954     }
00955 
00956   if ($arr_notif['ASSIGNEE']['ROLE_CHANGE'] &&
00957       (($changes['assigned_to']['add'] == $user_name) || ($changes['assigned_to']['del'] == $user_name)) &&
00958       ($role == 'ASSIGNEE') )
00959     {
00960       #echo "DBG ROLE_CHANGE for role assignee notified<br />";
00961       return true;
00962     }
00963 
00964   $arr_cc_changes = array();
00965   if (isset($changes['CC']['add']))
00966     $arr_cc_changes = split(',',$changes['CC']['add']);
00967   $arr_cc_changes[] = $changes['CC']['del'];
00968   $is_user_in_cc_changes = in_array($user_name,$arr_cc_changes);
00969   $are_anyother_user_in_cc_changes =
00970      (!$is_user_in_cc_changes || count($arr_cc_changes)>1);
00971 
00972   if ($arr_notif['CC']['ROLE_CHANGE'] && ($role == 'CC'))
00973     {
00974       if ($is_user_in_cc_changes)
00975         {
00976           #echo "DBG ROLE_CHANGE for cc notified<br />";
00977           return true;
00978         }
00979     }
00980 
00981   #----------------------------------------------------------
00982   #Check: CC_CHANGE  (CC_CHANGE is added or removed)
00983   # check this right after because  role cahange for cc can contradict
00984   # thee cc_change notification. If the role change on cc says no notification
00985   # then it has precedence over a cc_change
00986   if ($arr_notif[$role]['CC_CHANGE'] && isset($changes['CC']))
00987     {
00988       # its enough to test role against 'CC' because if we are at that point
00989       # it means that the role_change for CC was false or that role is not CC
00990       # So if role is 'CC' and we are here it means that the user asked to not be
00991       # notified on role_change as CC, unless other users are listed in the cc changes
00992       if (($role != 'CC') || (($role == 'CC') && $are_anyother_user_in_cc_changes))
00993         {
00994           #echo "DBG CC_CHANGE notified<br />";
00995           return true;
00996         }
00997     }
00998 
00999 
01000   #----------------------------------------------------------
01001   #Check: CHANGE_OTHER  (Any changes not mentioned above)
01002   # *** THIS ONE MUST ALWAYS BE TESTED LAST
01003 
01004   # Delete all tested fields from the $changes array. If any remains then it
01005   # means a notification must be sent
01006   unset($changes['details']);
01007   unset($changes['attach']);
01008   unset($changes['priority']);
01009   unset($changes['severity']);
01010   unset($changes['status_id']);
01011   unset($changes['CC']);
01012 
01013 # assignee and submitter related changes can't be unset globally. 
01014 # What needs to be unset is only what has been handled in this particular
01015 # call of the function
01016 
01017   if (($changes['assigned_to']['add'] == $user_name) && ($role == 'ASSIGNEE')) {    unset($changes['assigned_to']['add']);
01018   }
01019   if (($changes['assigned_to']['del'] == $user_name) && ($role == 'ASSIGNEE')) {    unset($changes['assigned_to']['del']);
01020   }
01021   if (count($changes['assigned_to']) == 0) { unset($changes['assigned_to']);}
01022                                                                                 
01023   if (($changes['submitted_by']['add'] == $user_name) && ($role == 'SUBMITTER')) {
01024     unset($changes['submitted_by']['add']);
01025   }
01026   if (($changes['submitted_by']['del'] == $user_name) && ($role == 'SUBMITTER')) {
01027     unset($changes['submitted_by']['del']);
01028   }
01029   if (count($changes['submitted_by']) == 0) { unset($changes['submitted_by']);}
01030 
01031   if ($arr_notif[$role]['ANY_OTHER_CHANGE'] && count($changes))
01032     {
01033       #echo "DBG ANY_OTHER_CHANGE notified<br />";
01034       return true;
01035     }
01036 
01037   # Sorry, no notification...
01038   #echo "DBG No notification!!<br />";
01039   return false;
01040 }
01041 
01042 function trackers_build_notification_list($item_id, $group_id, $changes)
01043 {
01044 
01045   $sql="SELECT assigned_to, submitted_by from ".ARTIFACT." WHERE bug_id='$item_id'";
01046   $res_as=db_query($sql);
01047 
01048   # Rk: we store email addresses in a hash to make sure they are only
01049   # stored once. Normally if an email is repeated several times sendmail
01050   # would take care of it but I prefer taking care of it now.
01051   # Same for user ids.
01052   # We also use the user_ids hash to check if a user has already been selected for
01053   # notification. If so it is not necessary to check it again in another role.
01054   $addresses = array();
01055   $user_ids = array();
01056 
01057   # check submitter notification preferences
01058   $user_id = db_result($res_as,0,'submitted_by');
01059   if ($user_id != 100)
01060     {
01061       if (trackers_check_notification($user_id, 'SUBMITTER', $changes))
01062         {
01063           $user_ids[$user_id] = true;
01064         }
01065     }
01066 
01067   # check assignee  notification preferences
01068   $user_id = db_result($res_as,0,'assigned_to');
01069   if ($user_id != 100)
01070     {
01071       if (!$user_ids[$user_id] && trackers_check_notification($user_id, 'ASSIGNEE', $changes))
01072         {
01073           $user_ids[$user_id] = true;
01074         }
01075     }
01076 
01077   # check old assignee  notification preferences if assignee was just changed
01078   $user_name = $changes['assigned_to']['del'];
01079   if ($user_name)
01080     {
01081       $res_oa = user_get_result_set_from_unix($user_name);
01082       $user_id = db_result($res_oa,0,'user_id');
01083       if ($user_id != 100 && !$user_ids[$user_id] && trackers_check_notification($user_id, 'ASSIGNEE', $changes))
01084         {
01085           $user_ids[$user_id] = true;
01086         }
01087     }
01088 
01089   # check all CC
01090   # a) check all the people in the current CC list
01091   # b) check the CC that has just been removed if any and see if she
01092   # wants to be notified as well
01093   # if the CC indentifier is an email address then notify in any case
01094   # because this user has no personal setting
01095   $res_cc = trackers_data_get_cc_list($item_id);
01096   $arr_cc = array();
01097   if ($res_cc && (db_numrows($res_cc) > 0))
01098     {
01099       while ($row = db_fetch_array($res_cc))
01100         {
01101           $arr_cc[] = $row['email'];
01102         }
01103     }
01104   # Only one CC can be deleted at once so just append it to the list....
01105   $arr_cc[] = $changes['CC']['del'];
01106 
01107   while (list(,$cc) = each($arr_cc))
01108     {
01109       if (validate_email($cc))
01110         {
01111           $addresses[utils_normalize_email($cc)] = true;
01112         }
01113       else
01114         {
01115           $res = user_get_result_set_from_unix($cc);
01116           $user_id = db_result($res,0,'user_id');
01117           if (!$user_ids[$user_id] && trackers_check_notification($user_id, 'CC', $changes))
01118             {
01119               $user_ids[$user_id] = true;
01120             }
01121         }
01122     } # while
01123 
01124 
01125   # check all commenters
01126   $res_com = trackers_data_get_commenters($item_id);
01127   if (db_numrows($res_com) > 0)
01128     {
01129       while ($row = db_fetch_array($res_com))
01130         {
01131           $user_id = $row['mod_by'];
01132           if ($user_id != 100)
01133             {
01134               if (!$user_ids[$user_id] && trackers_check_notification($user_id, 'COMMENTER', $changes))
01135                 {
01136                   $user_ids[$user_id] = true;
01137                 }
01138             }
01139         }
01140     }
01141 
01142   # build the final list of email addresses
01143   reset($user_ids);
01144   while (list($user_id,) = each($user_ids))
01145     {
01146       if ($user_id)
01147         {
01148           # Dirty hack: for a reason need to be cleared out,
01149           # a user_id = 0 arrived here.
01150           # Must not define email address so soon. Just passing user_id
01151           $addresses[$user_id] = true;
01152         }
01153     }
01154 
01155   # return an array with all the email addresses the notification must be sent to
01156   return (array_keys($addresses));
01157 
01158 }
01159 
01160 function trackers_mail_followup ($item_id,$more_addresses=false,$changes=false,$force_exclude_list=false, $artifact=0)
01161 {
01162   global $sys_datefmt;
01163 
01164   if (!$artifact)
01165     { $artifact = ARTIFACT; }
01166 
01167   $sql="SELECT * from $artifact WHERE bug_id='$item_id'";
01168 
01169   $result = db_query($sql);
01170   $bug_href = "http://".$GLOBALS['sys_default_domain'].$GLOBALS['sys_home']."$artifact/?$item_id";
01171 
01172   if ($result && db_numrows($result) > 0)
01173   {
01174 
01175   $group_id = db_result($result,0,'group_id');
01176 
01177   unset($content_type);
01178   # CERN SPECIFIC (at least for now) BEGIN '
01179   # Maybe later we ll implement a way to select mail templates, or prepared
01180   # mail format (like: text / html).
01181   # But it will have to be done in a well planned way that take into account
01182   # necessary cases and is not encumbered by very very specific things.
01183   # Until this happen, cern will use its own functions to deals with notif.
01184   # Indeed, this part will maintained and modified by CERN only.
01185   #
01186   # To ease maintainance, such specific things should usually not be added.
01187   # Please write to savane-dev if you intend to make such changes.
01188   # The upstream code cannot be cluttered by tons of things like that.
01189   # This is a one time exception, or almost, needed because this cannot
01190   # be directly merged in a generic way right now.
01191   if ($GLOBALS['sys_default_domain'] == "savannah.cern.ch" || $GLOBALS['sys_debug_cerntest'])
01192   {
01193     $content_type = group_get_preference($group_id, "notif_content");
01194     if ($content_type == "")
01195      {
01196        $content_type = '2';   # by default select maximum
01197      }
01198 
01199     # Now, if the content type is 0, go on with Savane standard notif.
01200     # If it s something else, use trackers_mail_followup_cernspecifichack()
01201     if ($content_type > 0)
01202      {
01203        return trackers_mail_followup_cernspecifichack($group_id,$bug_href,$result,$content_type,$item_id,$more_addresses,$changes,$force_exclude_list);
01204      }
01205   }
01206   # CERN SPECIFIC (at least for now) END
01207 
01208   # CONTENT OF THE MAIL MUST NOT BE TRANSLATED
01209 
01210   unset($body);
01211 
01212       if ($changes)
01213         {
01214           $body = format_item_changes($changes, $item_id, $group_id)."\n";
01215         }
01216       else
01217         {
01218       $body .= "URL:\n  <".$bug_href.">\n\n";
01219       $body .= trackers_field_display('summary', $group_id, db_result($result,0,'summary'),false,true,true,true)."\n";
01220       $body .= sprintf("%25s", "Project:").' '.group_getname($group_id)."\n";
01221       $body .= trackers_field_display('submitted_by', $group_id, db_result($result,0,'submitted_by'),false,true,true,true)."\n";
01222       $body .= trackers_field_display('date', $group_id, db_result($result,0,'date'),false,true,true,true)."\n";
01223 
01224       # All other regular fields now
01225       $i=0;
01226       while ($field_name = trackers_list_all_fields())
01227       {
01228 
01229           # if the field is a special field or if not used by his project
01230           # then skip it. Otherwise print it in ASCII format.
01231           if (!trackers_data_is_special($field_name) &&
01232               trackers_data_is_used($field_name))
01233             {
01234 
01235               $body .= trackers_field_display($field_name,
01236                                               $group_id,
01237                                               db_result($result,0,$field_name),
01238                                               false,
01239                                               true,
01240                                               true,
01241                                               true);
01242 
01243               $i++;
01244               $body .= "\n";
01245             }
01246         }
01247       $body .= "\n";
01248 
01249       # Now display other special fields
01250       $body .= "    _______________________________________________________\n\nDetails:\n".trackers_field_display('details',
01251                                        $group_id,
01252                                        db_result($result,0,'details'),
01253                                        true,true,true,true);
01254 
01255       # Then output the history of bug details from newest to oldest
01256       $body .= "\n\n".format_item_details($item_id, $group_id, true);
01257 
01258       # Then output the CC list
01259       $body .= "\n\n".format_item_cc_list($item_id, $group_id, true);
01260 
01261       # Then output the history of bug details from newest to oldest
01262       $body .= "\n\n".format_item_attached_files($item_id, $group_id, true);
01263          }
01264 
01265       # Finally output the message trailer
01266       $body .= "\n    _______________________________________________________\n\n";
01267       $body .= "Reply to this item at:";
01268       $body .= "\n\n  <".$bug_href.">";
01269 
01270 
01271 
01272 
01273       # See who is going to receive the notification.
01274       # Plus append any other email
01275       # given at the end of the list.
01276       $arr_addresses = trackers_build_notification_list($item_id,$group_id,$changes);
01277       $to = join(',',$arr_addresses);
01278       $from = user_getrealname(0,1).' <'.$GLOBALS['sys_mail_replyto'].'@'.$GLOBALS['sys_mail_domain'].'>';
01279       $subject = utils_unconvert_htmlspecialchars(db_result($result,0,'summary'));
01280 
01281       if ($more_addresses)
01282         {
01283           $to .= ($to ? ',':'').$more_addresses;
01284         }
01285 
01286       # If the item is private, take into account the exclude-list
01287       if (db_result($result,0,'privacy') == '2')
01288         {
01289            $exclude_list = db_result(db_query("SELECT ".$artifact."_private_exclude_address FROM groups WHERE group_id='$group_id'"),0, $artifact."_private_exclude_address");
01290 
01291         }
01292 
01293       # Disallow mail notification for an address, private or not
01294       if ($force_exclude_list)
01295       {
01296         if ($exclude_list)
01297           { $exclude_list .= ",".$force_exclude_list; }
01298         else
01299           { $exclude_list = $force_exclude_list; }
01300       }
01301 
01302 
01303       sendmail_mail($from, $to, $subject, $body, group_getunixname($group_id), $artifact, $item_id, 0, 0, $exclude_list);
01304       # Useless feedback, already added by sendmail_mail()
01305       #fb(_("Item update sent."));
01306 
01307     }


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