Go to the source code of this file.
Functions | |
| 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 .= ' '; } 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: $date_begin<br />End: $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':'').'>></OPTION>'. 00420 '<OPTION VALUE="="'.(($value == '=') ? ' SELECTED':'').'>=</OPTION>'. 00421 '<OPTION VALUE="<"'.(($value == '<') ? ' SELECTED':'').'><</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 }
|
1.4.4