4 * SourceForge Generic Tracker facility
6 * SourceForge: Breaking Down the Barriers to Open Source Development
7 * Copyright 1999-2001 (c) VA Linux Systems
8 * http://sourceforge.net
13 require_once $gfcommon.'tracker/ArtifactType.class.php';
14 require_once $gfcommon.'tracker/ArtifactExtraField.class.php';
15 require_once $gfcommon.'tracker/ArtifactExtraFieldElement.class.php';
16 require_once $gfcommon.'tracker/ArtifactWorkflow.class.php';
17 require_once $gfcommon.'include/utils_crossref.php';
19 class ArtifactTypeHtml extends ArtifactType {
22 * ArtifactType() - constructor
24 * @param $Group object
25 * @param $artifact_type_id - the id # assigned to this artifact type in the db
27 function ArtifactTypeHtml(&$Group,$artifact_type_id=false, $arr=false) {
28 return $this->ArtifactType($Group,$artifact_type_id,$arr);
31 function header($params) {
32 global $HTML, $sys_use_tracker;
33 if (!$sys_use_tracker) {
36 $group_id= $this->Group->getID();
38 //required by new site_project_header
39 $params['group']=$group_id;
40 $params['toptab']='tracker';
41 $params['tabtext']=$this->getName();
43 site_project_header($params);
48 $labels[] = $this->getName().': '._('Browse');
49 $links[] = '/tracker/?func=browse&group_id='.$group_id.'&atid='. $this->getID();
50 $labels[] = _('Download .csv');
51 $links[] = '/tracker/?func=downloadcsv&group_id='.$group_id.'&atid='. $this->getID();
52 if ($this->allowsAnon() || session_loggedin()) {
53 $labels[] = _('Submit New');
54 $links[] = '/tracker/?func=add&group_id='.$group_id.'&atid='. $this->getID();
57 if (session_loggedin()) {
58 $labels[] = _('Reporting');
59 $links[] = '/tracker/reporting/?group_id='.$group_id.'&atid='. $this->getID();
60 if ($this->isMonitoring()) {
61 $labels[] = _('Stop Monitor');
62 $links[] = '/tracker/?group_id='.$group_id.'&atid='. $this->getID().'&func=monitor&stop=1';
64 $labels[] = _('Monitor');
65 $links[] = '/tracker/?group_id='.$group_id.'&atid='. $this->getID().'&func=monitor&start=1';
68 if ($this->userIsAdmin()) {
69 $labels[] = _('Admin');
70 $links[] = '/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID();
73 $labels[] = _('Monitor');
74 $links[] = '/tracker/?group_id='.$group_id.'&atid='. $this->getID().'&func=monitor&start=1';
77 echo $HTML->subMenu($labels,$links);
80 plugin_hook ("blocks", "tracker_".$this->getName());
84 function footer($params) {
85 site_project_footer($params);
88 function adminHeader($params) {
90 echo $this->header($params);
91 $group_id= $this->Group->getID();
93 $links_arr[]='/tracker/admin/?group_id='.$group_id;
94 $title_arr[]=_('New Tracker');
96 $links_arr[]='/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID().'&update_type=1';
97 $title_arr[]=_('Update Settings');
99 $links_arr[]='/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID().'&add_extrafield=1';
100 $title_arr[]=_('Manage Custom Fields');
102 $links_arr[]='/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID().'&workflow=1';
103 $title_arr[]=_('Manage Workflow');
105 $links_arr[]='/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID().'&customize_list=1';
106 $title_arr[]=_('Customize List');
108 $links_arr[]='/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID().'&clone_tracker=1';
109 $title_arr[]=_('Clone Tracker');
111 $links_arr[]='/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID().'&add_canned=1';
112 $title_arr[]=_('Add Canned Responses');
114 $links_arr[]='/tracker/admin/?group_id='.$group_id.'&atid='.$this->getID().'&delete=1';
115 $title_arr[]=_('Delete');
117 echo $HTML->printSubMenu($title_arr,$links_arr);
120 function adminFooter($params) {
121 echo $this->footer($params);
124 function renderSubmitInstructions() {
125 $msg = $this->getSubmitInstructions();
126 return str_replace("\n","<br />", $msg);
129 function renderBrowseInstructions() {
130 $msg = $this->getBrowseInstructions();
131 return str_replace("\n","<br />", $msg);
134 function renderExtraFields($selected=array(),$show_100=false,$text_100='none',$show_any=false,$text_any='Any',$filter='',$status_show_100=false,$mode='') {
135 $efarr = $this->getExtraFields($filter);
136 //each two columns, we'll reset this and start a new row
138 $template = $this->getRenderHTML($filter, $mode);
140 if ($mode=='QUERY') {
141 $keys=array_keys($efarr);
142 for ($k=0; $k<count($keys); $k++) {
144 if ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_SELECT ||
145 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_CHECKBOX ||
146 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_RADIO ||
147 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_STATUS ||
148 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_MULTISELECT) {
149 $efarr[$i]['field_type'] = ARTIFACT_EXTRAFIELDTYPE_MULTISELECT;
151 $efarr[$i]['field_type'] = ARTIFACT_EXTRAFIELDTYPE_TEXT;
156 // 'DISPLAY' mode is for renderding in 'read-only' mode (for detail view).
157 if ($mode === 'DISPLAY') {
158 $keys=array_keys($efarr);
159 for ($k=0; $k<count($keys); $k++) {
161 $value = $selected[$efarr[$i]['extra_field_id']];
162 if ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_SELECT ||
163 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_CHECKBOX ||
164 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_RADIO ||
165 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_STATUS ||
166 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_MULTISELECT) {
170 $arr =& $this->getExtraFieldElements($efarr[$i]['extra_field_id']);
172 // Convert the values (ids) to names in the ids order.
174 for ($j=0; $j<count($arr); $j++) {
175 if (is_array($value)) {
176 if (in_array($arr[$j]['element_id'],$value))
177 $new[]= $arr[$j]['element_name'];
178 } elseif ($arr[$j]['element_id'] === $value) {
179 $new[] = $arr[$j]['element_name'];
182 $value = join('<br />', $new);
184 } else if ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_TEXT ||
185 $efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_TEXTAREA) {
186 $value = preg_replace('/((http|https|ftp):\/\/\S+)/',
187 "<a href=\"\\1\" target=\"_blank\">\\1</a>", $value);
188 } else if ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_RELATION) {
189 // Convert artifact id to links.
190 $value = preg_replace('/\b(\d+)\b/e', "_artifactid2url('\\1')", $value);
192 $template = str_replace('<!--'.$efarr[$i]['field_name'].'-->',$value,$template);
198 $keys=array_keys($efarr);
199 for ($k=0; $k<count($keys); $k++) {
203 if (!isset($selected[$efarr[$i]['extra_field_id']]))
204 $selected[$efarr[$i]['extra_field_id']] = '';
206 if ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_SELECT) {
207 $str = $this->renderSelect($efarr[$i]['extra_field_id'],$selected[$efarr[$i]['extra_field_id']],$show_100,$text_100,$show_any,$text_any);
209 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_CHECKBOX) {
211 $str = $this->renderCheckbox($efarr[$i]['extra_field_id'],$selected[$efarr[$i]['extra_field_id']],$show_100,$text_100);
213 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_RADIO) {
215 $str = $this->renderRadio($efarr[$i]['extra_field_id'],$selected[$efarr[$i]['extra_field_id']],$show_100,$text_100,$show_any,$text_any);
217 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_TEXT) {
219 $str = $this->renderTextField($efarr[$i]['extra_field_id'],$selected[$efarr[$i]['extra_field_id']],$efarr[$i]['attribute1'],$efarr[$i]['attribute2']);
220 if ($mode == 'QUERY') {
221 $post_name = ' <i>'._('(% for wildcards)').'</i> ';
224 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_TEXTAREA) {
226 $str = $this->renderTextArea($efarr[$i]['extra_field_id'],$selected[$efarr[$i]['extra_field_id']],$efarr[$i]['attribute1'],$efarr[$i]['attribute2']);
227 if ($mode == 'QUERY') {
228 $post_name = ' <i>'._('(% for wildcards)').'</i> ';
231 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_MULTISELECT) {
233 $str = $this->renderMultiSelectBox ($efarr[$i]['extra_field_id'],$selected[$efarr[$i]['extra_field_id']],$show_100,$text_100);
235 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
237 // Get the allowed values from the workflow.
238 $atw = new ArtifactWorkflow($this, $efarr[$i]['extra_field_id']);
240 // Special treatement for the initial step (Submit).
241 // In this case, the initial value is the first value.
242 if ($selected === true) {
243 $selected_node = 100;
244 } elseif (isset($selected[$efarr[$i]['extra_field_id']]) && $selected[$efarr[$i]['extra_field_id']]) {
245 $selected_node = $selected[$efarr[$i]['extra_field_id']];
247 $selected_node = 100;
250 $allowed = $atw->getNextNodes($selected_node);
251 $allowed[] = $selected_node;
252 $str = $this->renderSelect($efarr[$i]['extra_field_id'],$selected_node,$status_show_100,$text_100,$show_any,$text_any, $allowed);
254 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_RELATION) {
256 $str = $this->renderRelationField($efarr[$i]['extra_field_id'],$selected[$efarr[$i]['extra_field_id']],$efarr[$i]['attribute1'],$efarr[$i]['attribute2']);
257 if ($mode == 'UPDATE') {
258 $post_name = html_image('ic/forum_edit.gif','37','15',array('title'=>"Click to edit", 'alt'=>"Click to edit", 'onclick'=>"switch2edit(this, 'show$i', 'edit$i')", 'border'=>"0"));
261 $template = str_replace('<!--PostName:'.$efarr[$i]['field_name'].'-->',$post_name,$template);
262 $template = str_replace('<!--'.$efarr[$i]['field_name'].'-->',$str,$template);
264 if($template != NULL){
272 * @return string HTML template.
274 function getRenderHTML($filter='', $mode='') {
275 // Use template only for the browse (not for query or mass update)
276 if (($mode === 'DISPLAY' || $mode === 'DETAIL' || $mode === 'UPDATE')
277 && $this->data_array['custom_renderer']) {
278 return $this->data_array['custom_renderer'];
280 return $this->generateRenderHTML($filter, $mode);
287 * @return string HTML template.
289 function generateRenderHTML($filter='', $mode) {
290 $efarr =& $this->getExtraFields($filter);
291 //each two columns, we'll reset this and start a new row
294 <!-- Start Extra Fields Rendering -->
295 <!-- COLUMN NAMES MUST BE PRESERVED EXACTLY, INCLUDING CASE! -->
299 $keys=array_keys($efarr);
301 if ($count == 0) return '';
303 for ($k=0; $k<$count; $k++) {
306 // Do not show the required star in query mode (creating/updating a query).
307 $is_required = ($mode == 'QUERY' || $mode == 'DISPLAY') ? 0 : $efarr[$i]['is_required'];
308 $name = $efarr[$i]['field_name'].($is_required ? utils_requiredField() : '').': ';
309 $name = '<strong>'.$name.'</strong>';
311 if ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_SELECT) {
314 <td width="50%" valign="top">'.$name.'<br /><!--'.$efarr[$i]['field_name'].'--></td>';
316 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_CHECKBOX) {
319 <td width="50%" valign="top">'.$name.'<br /><!--'.$efarr[$i]['field_name'].'--></td>';
321 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_RADIO) {
324 <td width="50%" valign="top">'.$name.'<br /><!--'.$efarr[$i]['field_name'].'--></td>';
326 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_TEXT) {
328 //text fields might be really wide, so need a row to themselves.
329 if (($col_count == 1) && ($efarr[$i]['attribute1'] > 30)) {
339 <td width="'.(50*$colspan).'%" colspan="'.$colspan.'" valign="top">'.$name.'<!--PostName:'.$efarr[$i]['field_name'].'--><br /><!--'.$efarr[$i]['field_name'].'--></td>';
341 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_TEXTAREA) {
343 //text areas might be really wide, so need a row to themselves.
344 if (($col_count == 1) && ($efarr[$i]['attribute2'] > 30)) {
354 <td width="'.(50*$colspan).'%" colspan="'.$colspan.'" valign="top">'.$name.'<!--PostName:'.$efarr[$i]['field_name'].'--><br /><!--'.$efarr[$i]['field_name'].'--></td>';
356 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_MULTISELECT) {
359 <td width="50%" valign="top">'.$name.'<br /><!--'.$efarr[$i]['field_name'].'--></td>';
361 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
364 <td width="50%" valign="top">'.$name.'<br /><!--'.$efarr[$i]['field_name'].'--></td>';
366 } elseif ($efarr[$i]['field_type'] == ARTIFACT_EXTRAFIELDTYPE_RELATION) {
368 //text fields might be really wide, so need a row to themselves.
369 if (($col_count == 1) && ($efarr[$i]['attribute1'] > 30)) {
379 <td width="'.(50*$colspan).'%" colspan="'.$colspan.'" valign="top">'.$name.'<!--PostName:'.$efarr[$i]['field_name'].'--><br /><!--'.$efarr[$i]['field_name'].'--></td>';
383 //we've done two columns - if there are more to do, start a new row
384 if (($col_count == 2) && ($k != $count-1)) {
391 if ($col_count == 1) {
397 <!-- End Extra Fields Rendering -->';
402 * renderSelect - this function builds pop up
405 * @param int The ID of this field.
406 * @param string The item that should be checked
407 * @param string Whether to show the '100 row'
408 * @param string What to call the '100 row'
409 * @return box and choices
411 function renderSelect ($extra_field_id,$checked='xzxz',$show_100=false,$text_100='none',$show_any=false,$text_any='Any', $allowed=false) {
412 if ($text_100 == 'none'){
415 $arr =& $this->getExtraFieldElements($extra_field_id);
416 for ($i=0; $i<count($arr); $i++) {
417 $keys[$i]=$arr[$i]['element_id'];
418 $vals[$i]=$arr[$i]['element_name'];
420 return html_build_select_box_from_arrays ($keys,$vals,'extra_fields['.$extra_field_id.']',$checked,$show_100,$text_100,$show_any,$text_any, $allowed);
424 * renderRadio - this function builds radio buttons.
426 * @param int The ID of this field.
427 * @param string The item that should be checked
428 * @param string Whether to show the '100 row'
429 * @param string What to call the '100 row'
430 * @return radio buttons
432 function renderRadio ($extra_field_id,$checked='xzxz',$show_100=false,$text_100='none',$show_any=false,$text_any='Any') {
433 $arr =& $this->getExtraFieldElements($extra_field_id);
434 for ($i=0; $i<count($arr); $i++) {
435 $keys[$i]=$arr[$i]['element_id'];
436 $vals[$i]=$arr[$i]['element_name'];
438 return html_build_radio_buttons_from_arrays ($keys,$vals,'extra_fields['.$extra_field_id.']',$checked,$show_100,$text_100,$show_any,$text_any);
442 * renderCheckbox - this function builds checkboxes.
444 * @param int The ID of this field.
445 * @param array The items that should be checked
446 * @param string Whether to show the '100 row'
447 * @param string What to call the '100 row'
448 * @return radio buttons
450 function renderCheckbox ($extra_field_id,$checked=array(),$show_100=false,$text_100='none') {
451 if ($text_100 == 'none'){
454 if (!$checked || !is_array($checked)) {
457 $arr =& $this->getExtraFieldElements($extra_field_id);
460 <input type="checkbox" name="extra_fields['.$extra_field_id.'][]" value="100" '.
461 ((in_array(100,$checked)) ? 'checked="checked"' : '').'/> '.$text_100.'<br />';
463 for ($i=0; $i<count($arr); $i++) {
465 <input type="checkbox" name="extra_fields['.$extra_field_id.'][]" value="'.$arr[$i]['element_id'].'" '.
466 ((in_array($arr[$i]['element_id'],$checked)) ? 'checked="checked"' : '').'/> '.$arr[$i]['element_name'].'<br />';
472 * renderMultiSelectBox - this function builds checkboxes.
474 * @param int The ID of this field.
475 * @param array The items that should be checked
476 * @param string Whether to show the '100 row'
477 * @param string What to call the '100 row'
478 * @return radio multiselectbox
480 function renderMultiSelectBox ($extra_field_id,$checked=array(),$show_100=false,$text_100='none') {
481 $arr =& $this->getExtraFieldElements($extra_field_id);
485 if (!is_array($checked)) {
486 $checked = explode(',',$checked);
490 $arr =& $this->getExtraFieldElements($extra_field_id);
491 for ($i=0; $i<count($arr); $i++) {
492 $keys[]=$arr[$i]['element_id'];
493 $vals[]=$arr[$i]['element_name'];
495 $size = min( count($arr)+1, 15);
496 return html_build_multiple_select_box_from_arrays($keys,$vals,"extra_fields[$extra_field_id][]",$checked,$size,$show_100,$text_100);
500 * renderTextField - this function builds a text field.
502 * @param int The ID of this field.
503 * @param string The data for this field.
504 * @return text area and data.
506 function renderTextField ($extra_field_id,$contents,$size,$maxlength) {
508 <input type="text" name="extra_fields['.$extra_field_id.']" value="'.$contents.'" size="'.$size.'" maxlength="'.$maxlength.'"/>';
512 * renderRelationField - this function builds a relation field.
514 * @param int The ID of this field.
515 * @param string The data for this field.
516 * @return text area and data.
518 function renderRelationField ($extra_field_id,$contents,$size,$maxlength) {
519 $arr =& $this->getExtraFieldElements($extra_field_id);
520 for ($i=0; $i<count($arr); $i++) {
521 $keys[$i]=$arr[$i]['element_id'];
522 $vals[$i]=$arr[$i]['element_name'];
524 // Convert artifact id to links.
525 $html_contents = preg_replace('/\b(\d+)\b/e', "_artifactid2url('\\1','title')", $contents);
526 $edit_contents = $this->renderTextField ($extra_field_id,$contents,$size,$maxlength);
527 $edit_tips = '<br/><span class="tips">'._('Tip: Enter a space-separated list of artifact ids ([#NNN] also accepted)').'</span>';
529 <div id="edit'.$extra_field_id.'" style="display: none;">'.$edit_contents.$edit_tips.'</div>
530 <div id="show'.$extra_field_id.'" style="display: block;">'.$html_contents.'</div>';
534 * renderTextArea - this function builds a text area.
536 * @param int The ID of this field.
537 * @param string The data for this field.
538 * @return text area and data.
540 function renderTextArea ($extra_field_id,$contents,$rows,$cols) {
542 <textarea name="extra_fields['.$extra_field_id.']" rows="'.$rows.'" cols="'.$cols.'">'.$contents.'</textarea>';
545 function technicianBox ($name='assigned_to[]',$checked='xzxz',$show_100=true,$text_100='none',$extra_id='-1',$extra_name='',$multiple=false) {
546 if ($text_100=='none'){
547 $text_100=_('Nobody');
549 $result = $this->getTechnicians();
550 // this was a bad hack to allow you to mass-update to unassigned, which is ID=100, which
551 // conflicted with the "No Change" ID of 100.
552 $ids =& util_result_column_to_array($result,0);
553 $names =& util_result_column_to_array($result,1);
554 if ($extra_id != '-1') {
556 $names[]=$extra_name;
560 if (!is_array($checked)) {
561 $checked = explode(',',$checked);
563 $size = min( count($ids)+1, 15);
564 return html_build_multiple_select_box_from_arrays ($ids,$names,$name,$checked,$size,$show_100,$text_100);
566 return html_build_select_box_from_arrays ($ids,$names,$name,$checked,$show_100,$text_100);
570 function cannedResponseBox ($name='canned_response',$checked='xzxz') {
571 return html_build_select_box ($this->getCannedResponses(),$name,$checked);
575 * statusBox - show the statuses - automatically shows the "custom statuses" if they exist
579 function statusBox ($name='status_id',$checked='xzxz',$show_100=false,$text_100='none') {
580 if ($text_100=='none'){
583 return html_build_select_box($this->getStatuses(),$name,$checked,$show_100,$text_100);
590 // c-file-style: "bsd"