2 /*=====================================================================*\
3 || ###################################################################
5 || # Copyright ©2002-2007 Blue Static
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version 2 of the License.
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
25 * This class is used to sort bugs based on user-sent options and variables.
28 * @copyright Copyright ©2002 - 2007, Blue Static
57 * Current sort direction
64 * Column array for table heads
69 // ###################################################################
71 * Constructor: set the page name
75 * @param string File name without the .php extension
77 function ListSorter($page)
80 $this->registry
= $bugsys;
82 $this->process_incoming();
85 // ###################################################################
87 * Processes the incoming variables and then sets all the sort order
88 * information appropriately
92 function process_incoming()
94 $this->sortkey
= $this->registry
->in
['by'];
95 if (!$this->fetch_by_text($this->registry
->in
['by']))
97 $this->sortkey
= (isset($this->registry
->userinfo
['defaultsortkey']) ?
$this->registry
->userinfo
['defaultsortkey'] : $this->registry
->options
['defaultsortkey']);
100 $this->direction
= $this->registry
->in
['as'];
101 if (!in_array($this->direction
, array('asc', 'desc')))
103 $this->direction
= (isset($this->registry
->userinfo
['defaultsortas']) ?
$this->registry
->userinfo
['defaultsortas'] : $this->registry
->options
['defaultsortas']);
107 // ###################################################################
109 * Fetch a SQL query to gather bugs with the sort filters applied
113 * @param string Additional WHERE clauses in an array
114 * @param string A LIMIT clause
116 * @return string Compiled SQL query
118 function fetch_sql_query($where = null
, $limit = null
)
120 // this WHERE clause is used for all the queries
121 $basewhere = "bug.product IN (" . fetch_on_bits('canviewbugs') . ")
122 AND (!bug.hidden OR (bug.hidden AND bug.product IN (" . fetch_on_bits('canviewhidden') . "))" . (can_perform('canviewownhidden') ?
" OR (bug.hidden AND bug.userid = " . $this->registry
->userinfo
['userid'] . " AND bug.product IN (" . fetch_on_bits('canviewownhidden') . "))" : "") . ")" .
123 (($this->registry
->options
['hidestatuses'] OR isset($this->registry
->userinfo
['hidestatuses'])) ?
"
124 AND bug.status NOT IN (" . ($this->registry
->userinfo
['hidestatuses'] != '' ?
$this->registry
->userinfo
['hidestatuses'] : $this->registry
->options
['hidestatuses']) . ")" : "");
126 // remap the sort keys to be actual SQL fields
129 'summary' => 'summary',
130 'reporter' => 'userid',
131 'lastpost' => (can_perform('canviewhidden') ?
"lastposttime" : "hiddenlastposttime"),
132 'assignedto'=> 'assignedto'
135 switch ($this->sortkey
)
143 SELECT bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "bug AS bug
144 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
145 ON (bug.bugid = vote.bugid)
147 (is_array($where) ?
"
148 AND " . implode("\nAND ", $where) : "") . "
149 ORDER BY " . $querykeys[ $this->sortkey
] . " " . strtoupper($this->direction
) . ($this->sortkey
!= 'lastpost' ?
", " . $querykeys['lastpost'] . " " . strtoupper($this->direction
) : "") . ($limit ?
"
159 $key = ($this->sortkey
!= 'component' ?
$this->sortkey
: 'product');
161 SELECT $key.*, bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "$key AS $key
162 RIGHT JOIN " . TABLE_PREFIX
. "bug AS bug
163 ON (bug.$key = $key.{$key}id)
164 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
165 ON (bug.bugid = vote.bugid)
167 (is_array($where) ?
"
168 AND " . implode("\nAND ", $where) : "") . "
169 ORDER BY $key.displayorder " . strtoupper($this->direction
) . ", bug.$querykeys[lastpost] " . strtoupper($this->direction
) . ($limit ?
"
174 SELECT bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "bug AS bug
175 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
176 ON (bug.bugid = vote.bugid)
178 (is_array($where) ?
"
179 AND " . implode("\nAND ", $where) : "") . "
180 ORDER BY vote.votefor " . strtoupper($this->direction
) . ", vote.voteagainst " . strtoupper($this->fetch_opposite_sort_direction()) . ", bug.$querykeys[lastpost] " . strtoupper($this->direction
) . ($limit ?
"
184 if (substr($this->sortkey
, 0, 6) != 'custom')
190 SELECT bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "bug AS bug
191 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
192 ON (bug.bugid = vote.bugid)
194 (is_array($where) ?
"
195 AND " . implode("\nAND ", $where) : "") . "
196 ORDER BY {$this->sortkey} " . strtoupper($this->direction
) . ", " . $querykeys['lastpost'] . " " . strtoupper($this->direction
) . ($limit ?
"
203 // ###################################################################
205 * Returns the display text for a given sort order key
207 * @access public static
209 * @param string Sort order key, or FALSE for the array
210 * @param bool Permission check the custom fields?
212 * @return mixed Display text if param is string, or array of all key=>text if param is NULL
214 function fetch_by_text($key, $doPerm = true
)
219 'lastpost' => T('Last Post Time'),
220 'bugid' => T('Bug ID'),
221 'summary' => T('Summary'),
222 'reporter' => T('Reporter'),
223 'product' => T('Product'),
224 'component' => T('Component'),
225 'version' => T('Version'),
226 'status' => T('Status'),
227 'resolution' => T('Resolution'),
228 'priority' => T('Priority'),
229 'severity' => T('Severity'),
230 'votes' => T('Votes'),
231 'assignedto' => T('Assigned To')
234 $fields = self
::_fetchCustomFields($doPerm);
235 foreach ($fields AS $field)
237 $keys['custom' . $field['fieldid']] = $field['name'];
246 return $keys["$key"];
250 // ###################################################################
252 * Returns the display text for a given sort order direction
254 * @access public static
256 * @param string Sort direction, or FALSE for the array
258 * @return mixed Display text if param is string, or array of all key=>text if param is NULL
260 function fetch_as_text($key)
265 'desc' => T('Descending'),
266 'asc' => T('Ascending')
275 return $keys["$key"];
279 // ###################################################################
281 * Returns a multi-dimensional array with sort by keys indexing arrays
282 * with 'image' and 'href' keys that store the values from
283 * fetch_sort_image() and fetch_sort_link(), respectively
287 * @param string Extra GET parameters to pass to fetch_sort_link()
289 * @return array Array as described above
291 function fetch_display_array($params = null
)
293 $return = $this->fetch_by_text(false
);
295 foreach ($return AS $key => $nil)
297 $return["$key"] = array('image' => ($this->sortkey
== $key ?
$this->fetch_sort_image() : ''), 'href' => $this->fetch_sort_link($key, $params, true
));
303 // ###################################################################
305 * Returns the entire <img> tag for the sort arrow
309 * @return string HTML <img> tag
311 function fetch_sort_image()
313 return '<img src="templates/images/arrow_' . $this->fetch_sort_direction() . '.gif" alt="" style="vertical-align: top; border: none" />';
316 // ###################################################################
318 * Returns the href value for an <a> tag by generating all the necessary
319 * bits and concat'ing it onto an extra string of GETs (optional)
323 * @param string Sorting key
324 * @param string Additional GET parameters
325 * @param bool Highlight the current sortkey if that's passed?
327 * @return string HREF
329 function fetch_sort_link($key, $params = null
, $highlight = false
)
336 return $this->page
. '.php?' . $params . 'by=' . $key . '&as=' . (($this->sortkey
== $key AND $highlight) ?
$this->fetch_opposite_sort_direction() . '" class="select' : $this->fetch_sort_direction());
339 // ###################################################################
341 * Returns the OPPOSITE direction to sort when you click on a link
345 * @return string Either asc or desc
347 function fetch_opposite_sort_direction()
349 if ($this->direction
== 'asc')
359 // ###################################################################
361 * Returns the current sorted direction for the image path
365 * @return string Either asc or desc
367 function fetch_sort_direction()
369 return $this->direction
;
372 // ###################################################################
374 * Returns the HTML code for bug listing table column headers
376 * @param bool Include the sort links/image?
377 * @param string Additional GET params to pass to fetch_sort_link()
379 * @return string HTML code
381 function constructColumnHeaders($sortable, $params = null
)
383 $this->_processColumns();
385 $names = self
::fetch_by_text(false
);
388 foreach ($this->columns
AS $columns)
391 foreach ($columns AS $column)
393 $build[] = ($sortable ?
'<a href="' . $this->fetch_sort_link($column, $params, true
) . '">' . $names[$column] . '</a>' : $names[$column]);
395 $image = ((in_array($this->sortkey
, $columns) AND $sortable) ?
$this->fetch_sort_image() : '');
396 $name = implode(' / ', $build);
397 eval('$output .= "' . $this->registry
->template
->fetch('list_head') . '";');
403 // ###################################################################
405 * Returns the HTML code for a row of data for the bug listing
407 * @param array Bug data array
408 * @param string Additional link params
410 * @return string Row HTML
412 function constructRow($bug, $params = null
)
416 $this->_processColumns();
418 foreach ($this->columns
AS $columns)
420 if (sizeof($columns) > 1)
423 foreach ($columns AS $column)
425 $build[] = $this->_processDataForColumn($bug, $column, $params, true
);
427 $data = "\n\t\t" . implode("\n\t\t", $build) . "\n\t";
431 $data = $this->_processDataForColumn($bug, $columns[0], $params, false
);
433 $fields .= "\n\t<td>$data</td>";
436 eval('$output = "' . $this->registry
->template
->fetch('trackerhome_bits') . '";');
440 // ###################################################################
442 * Handler for special-case column data
444 * @param array Bug data
445 * @param string Column name
446 * @param string Additional URL params
447 * @param bool Will this column have multiple data sets?
449 * @return string Processed column data
451 function _processDataForColumn($bug, $column, $params = null
, $multi = false
)
453 $open = ($multi ?
'<div>' : '');
454 $close = ($multi ?
'</div>' : '');
458 return $open . '<a href="showreport.php?bugid=' . $bug['bugid'] . $params . '">' . $bug['summary'] . '</a>' . $close;
460 return $open . ($bug['userid'] ?
$bug['username'] : T('Guest')) . $close;
462 return "\n\t\t<div>" . $bug['lastposttime'] . "</div>\n\t\t<div>" . T('by') . ' ' . ($bug['lastpost'] ?
$bug['lastpost'] : T('Guest')) . "</div>\n\t";
464 return "\n\t\t<div>" . T('For:') . ' ' . $bug['votefor'] . "</div>\n\t\t<div>" . T('Against:') . ' ' . $bug['voteagainst'] . "</div>\n\t";
466 return $open . $bug["$column"] . $close;
470 // ###################################################################
472 * Sets up $this->columns so that the data can be processed more
475 function _processColumns()
477 if (is_array($this->columns
))
482 $columns = self
::fetch_by_text(false
);
484 $array = (($this->registry
->userinfo
['userid'] AND is_array($this->registry
->userinfo
['columnoptions'])) ?
$this->registry
->userinfo
['columnoptions'] : $this->registry
->options
['columnoptions']);
486 foreach ($array AS $column => $position)
488 // the column doesn't exist, or more likely, we don't have permission to view it
489 if (!isset($columns[$column]))
495 $this->columns
["$position"][] = $column;
499 ksort($this->columns
);
502 // ###################################################################
504 * Returns an array of all the custom fields that the current user
505 * has permission to use
507 * @param boolean Ignore permissions?
511 private static function _fetchCustomFields($doPerm = true
)
514 static $fields = array(), $fieldsPerm = array();
516 if ($doPerm AND !empty($fieldsPerm))
520 else if (!$doPerm AND !empty($fields))
527 $fields_fetch = $bugsys->db
->query("
528 SELECT bugfield.*, MAX(permission.mask) AS mask
529 FROM " . TABLE_PREFIX
. "bugfield AS bugfield
530 LEFT JOIN " . TABLE_PREFIX
. "bugfieldpermission AS permission
531 ON (bugfield.fieldid = permission.fieldid)
532 WHERE (permission.mask = 2 OR permission.mask = 1)
533 AND permission.usergroupid IN ({$bugsys->userinfo['usergroupid']}" . (sizeof($bugsys->userinfo
['groupids']) != 0 ?
',' . implode(',', $bugsys->userinfo
['groupids']) : '') . ")
534 GROUP BY (bugfield.fieldid)
539 $fields_fetch = $bugsys->db
->query("SELECT * FROM " . TABLE_PREFIX
. "bugfield");
542 while ($field = $bugsys->db
->fetch_array($fields_fetch))
546 $fieldsPerm[$field['fieldid']] = $field;
550 $fields[$field['fieldid']] = $field;
557 /*=====================================================================*\
558 || ###################################################################
561 || ###################################################################
562 \*=====================================================================*/