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
54 * Current sort direction
57 private $direction = '';
60 * Column array for table heads
66 * Constructor: set the page name
68 * @param string File name without the .php extension
70 public function __construct($page)
72 $this->db
= BSApp
::$db;
74 $this->_processIncoming();
78 * Processes the incoming variables and then sets all the sort order
79 * information appropriately
81 private function _processIncoming()
83 $this->sortkey
= BSApp
::$input->in
['by'];
84 if (!self
::fetch_by_text(BSApp
::$input->in
['by']))
86 $this->sortkey
= (isset(bugdar
::$userinfo['defaultsortkey']) ? bugdar
::$userinfo['defaultsortkey'] : bugdar
::$options['defaultsortkey']);
89 $this->direction
= BSApp
::$input->in
['as'];
90 if (!in_array($this->direction
, array('asc', 'desc')))
92 $this->direction
= (isset(bugdar
::$userinfo['defaultsortas']) ? bugdar
::$userinfo['defaultsortas'] : bugdar
::$options['defaultsortas']);
97 * Fetch a SQL query to gather bugs with the sort filters applied
99 * @param string Additional WHERE clauses in an array
100 * @param string A LIMIT clause
102 * @return string Compiled SQL query
104 public function fetchSqlQuery($where = null
, $limit = null
)
106 // this WHERE clause is used for all the queries
107 $basewhere = "bug.product IN (" . fetch_on_bits('canviewbugs') . ")
108 AND (!bug.hidden OR (bug.hidden AND bug.product IN (" . fetch_on_bits('canviewhidden') . "))" . (can_perform('canviewownhidden') ?
" OR (bug.hidden AND bug.userid = " . bugdar
::$userinfo['userid'] . " AND bug.product IN (" . fetch_on_bits('canviewownhidden') . "))" : "") . ")" .
109 ((bugdar
::$options['hidestatuses'] ||
isset(bugdar
::$userinfo['hidestatuses'])) ?
"
110 AND bug.status NOT IN (" . (bugdar
::$userinfo['hidestatuses'] != '' ? bugdar
::$userinfo['hidestatuses'] : bugdar
::$options['hidestatuses']) . ")" : "");
112 // remap the sort keys to be actual SQL fields
115 'summary' => 'summary',
116 'reporter' => 'userid',
117 'lastpost' => (can_perform('canviewhidden') ?
"lastposttime" : "hiddenlastposttime"),
118 'assignedto'=> 'assignedto'
121 switch ($this->sortkey
)
129 SELECT bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "bug AS bug
130 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
131 ON (bug.bugid = vote.bugid)
133 (is_array($where) ?
"
134 AND " . implode("\nAND ", $where) : "") . "
135 ORDER BY " . $querykeys[ $this->sortkey
] . " " . strtoupper($this->direction
) . ($this->sortkey
!= 'lastpost' ?
", " . $querykeys['lastpost'] . " " . strtoupper($this->direction
) : "") . ($limit ?
"
145 $key = ($this->sortkey
!= 'component' ?
$this->sortkey
: 'product');
147 SELECT $key.*, bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "$key AS $key
148 RIGHT JOIN " . TABLE_PREFIX
. "bug AS bug
149 ON (bug.$key = $key.{$key}id)
150 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
151 ON (bug.bugid = vote.bugid)
153 (is_array($where) ?
"
154 AND " . implode("\nAND ", $where) : "") . "
155 ORDER BY $key.displayorder " . strtoupper($this->direction
) . ", bug.$querykeys[lastpost] " . strtoupper($this->direction
) . ($limit ?
"
160 SELECT bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "bug AS bug
161 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
162 ON (bug.bugid = vote.bugid)
164 (is_array($where) ?
"
165 AND " . implode("\nAND ", $where) : "") . "
166 ORDER BY vote.votefor " . strtoupper($this->direction
) . ", vote.voteagainst " . strtoupper($this->fetchOppositeSortDirection()) . ", bug.$querykeys[lastpost] " . strtoupper($this->direction
) . ($limit ?
"
170 if (substr($this->sortkey
, 0, 6) != 'custom')
176 SELECT bug.*, vote.votefor, vote.voteagainst FROM " . TABLE_PREFIX
. "bug AS bug
177 LEFT JOIN " . TABLE_PREFIX
. "vote AS vote
178 ON (bug.bugid = vote.bugid)
180 (is_array($where) ?
"
181 AND " . implode("\nAND ", $where) : "") . "
182 ORDER BY {$this->sortkey} " . strtoupper($this->direction
) . ", " . $querykeys['lastpost'] . " " . strtoupper($this->direction
) . ($limit ?
"
190 * Returns the display text for a given sort order key
192 * @param string Sort order key, or FALSE for the array
193 * @param bool Permission check the custom fields?
195 * @return mixed Display text if param is string, or array of all key=>text if param is NULL
197 public static function fetch_by_text($key, $doPerm = true
)
200 'lastpost' => T('Last Post Time'),
201 'bugid' => T('Bug ID'),
202 'summary' => T('Summary'),
203 'reporter' => T('Reporter'),
204 'product' => T('Product'),
205 'component' => T('Component'),
206 'version' => T('Version'),
207 'status' => T('Status'),
208 'resolution' => T('Resolution'),
209 'priority' => T('Priority'),
210 'severity' => T('Severity'),
211 'votes' => T('Votes'),
212 'assignedto' => T('Assigned To')
215 $fields = self
::_fetch_custom_fields($doPerm);
216 foreach ($fields AS $field)
218 $keys['custom' . $field['fieldid']] = $field['name'];
227 return $keys["$key"];
232 * Returns the display text for a given sort order direction
234 * @param string Sort direction, or FALSE for the array
236 * @return mixed Display text if param is string, or array of all key=>text if param is NULL
238 public static function fetch_as_text($key)
241 'desc' => T('Descending'),
242 'asc' => T('Ascending')
251 return $keys["$key"];
256 * Returns a multi-dimensional array with sort by keys indexing arrays
257 * with 'image' and 'href' keys that store the values from
258 * fetchSortImage() and fetchSortLink(), respectively
260 * @param string Extra GET parameters to pass to fetchSortLink()
262 * @return array Array as described above
264 public function fetchDisplayArray($params = null
)
266 $return = self
::fetch_by_text(false
);
268 foreach ($return as $key => $nil)
270 $return["$key"] = array('image' => ($this->sortkey
== $key ?
$this->fetchSortImage() : ''), 'href' => $this->fetchSortLink($key, $params, true
));
277 * Returns the entire <img> tag for the sort arrow
279 * @return string HTML <img> tag
281 public function fetchSortImage()
283 return '<img src="templates/images/arrow_' . $this->fetchSortDirection() . '.gif" alt="" style="vertical-align: top; border: none" />';
287 * Returns the href value for an <a> tag by generating all the necessary
288 * bits and concat'ing it onto an extra string of GETs (optional)
290 * @param string Sorting key
291 * @param string Additional GET parameters
292 * @param bool Highlight the current sortkey if that's passed?
294 * @return string HREF
296 public function fetchSortLink($key, $params = null
, $highlight = false
)
303 return $this->page
. '.php?' . $params . 'by=' . $key . '&as=' . (($this->sortkey
== $key && $highlight) ?
$this->fetchOppositeSortDirection() . '" class="select' : $this->fetchSortDirection());
307 * Returns the OPPOSITE direction to sort when you click on a link
309 * @return string Either asc or desc
311 public function fetchOppositeSortDirection()
313 if ($this->direction
== 'asc')
324 * Returns the current sorted direction for the image path
326 * @return string Either asc or desc
328 public function fetchSortDirection()
330 return $this->direction
;
334 * Returns the HTML code for bug listing table column headers
336 * @param bool Include the sort links/image?
337 * @param string Additional GET params to pass to fetchSortLink()
339 * @return string HTML code
341 public function constructColumnHeaders($sortable, $params = null
)
343 $this->_processColumns();
345 $names = self
::fetch_by_text(false
);
348 foreach ($this->columns
as $columns)
351 foreach ($columns as $column)
353 $build[] = ($sortable ?
'<a href="' . $this->fetchSortLink($column, $params, true
) . '">' . $names[$column] . '</a>' : $names[$column]);
355 $image = ((in_array($this->sortkey
, $columns) && $sortable) ?
$this->fetchSortImage() : '');
356 $name = implode(' / ', $build);
358 $tpl = new BSTemplate('list_head');
363 $output .= $tpl->evaluate()->getTemplate();
370 * Returns the HTML code for a row of data for the bug listing
372 * @param array Bug data array
373 * @param string Additional link params
375 * @return string Row HTML
377 function constructRow($bug, $params = null
)
379 $this->_processColumns();
381 foreach ($this->columns
as $columns)
383 if (sizeof($columns) > 1)
386 foreach ($columns as $column)
388 $build[] = $this->_processDataForColumn($bug, $column, $params, true
);
390 $data = "\n\t\t" . implode("\n\t\t", $build) . "\n\t";
394 $data = $this->_processDataForColumn($bug, $columns[0], $params, false
);
396 $fields .= "\n\t<td>$data</td>";
399 $tpl = new BSTemplate('trackerhome_bits');
404 return $tpl->evaluate()->getTemplate();
408 * Handler for special-case column data
410 * @param array Bug data
411 * @param string Column name
412 * @param string Additional URL params
413 * @param bool Will this column have multiple data sets?
415 * @return string Processed column data
417 private function _processDataForColumn($bug, $column, $params = null
, $multi = false
)
419 $open = ($multi ?
'<div>' : '');
420 $close = ($multi ?
'</div>' : '');
424 return $open . '<a href="showreport.php?bugid=' . $bug['bugid'] . $params . '">' . $bug['summary'] . '</a>' . $close;
426 return $open . ($bug['userid'] ?
$bug['username'] : T('Guest')) . $close;
428 return "\n\t\t<div>" . $bug['lastposttime'] . "</div>\n\t\t<div>" . T('by') . ' ' . ($bug['lastpost'] ?
$bug['lastpost'] : T('Guest')) . "</div>\n\t";
430 return "\n\t\t<div>" . T('For:') . ' ' . $bug['votefor'] . "</div>\n\t\t<div>" . T('Against:') . ' ' . $bug['voteagainst'] . "</div>\n\t";
432 return $open . $bug["$column"] . $close;
437 * Sets up $this->columns so that the data can be processed more
440 private function _processColumns()
442 if (is_array($this->columns
))
447 $columns = self
::fetch_by_text(false
);
449 $array = ((bugdar
::$userinfo['userid'] && is_array(bugdar
::$userinfo['columnoptions'])) ? bugdar
::$userinfo['columnoptions'] : bugdar
::$options['columnoptions']);
451 foreach ($array as $column => $position)
453 // the column doesn't exist, or more likely, we don't have permission to view it
454 if (!isset($columns[$column]))
460 $this->columns
["$position"][] = $column;
464 ksort($this->columns
);
468 * Returns an array of all the custom fields that the current user
469 * has permission to use
471 * @param boolean Ignore permissions?
475 private static function _fetch_custom_fields($doPerm = true
)
477 static $fields = array(), $fieldsPerm = array();
479 if ($doPerm && !empty($fieldsPerm))
483 else if (!$doPerm && !empty($fields))
490 $fields_fetch = BSApp
::$db->query("
491 SELECT bugfield.*, MAX(permission.mask) AS mask
492 FROM " . TABLE_PREFIX
. "bugfield AS bugfield
493 LEFT JOIN " . TABLE_PREFIX
. "bugfieldpermission AS permission
494 ON (bugfield.fieldid = permission.fieldid)
495 WHERE (permission.mask = 2 OR permission.mask = 1)
496 AND permission.usergroupid IN (" . bugdar
::$userinfo['usergroupid'] . (sizeof(bugdar
::$userinfo['groupids']) != 0 ?
',' . implode(',', bugdar
::$userinfo['groupids']) : '') . ")
497 GROUP BY (bugfield.fieldid)
502 $fields_fetch = BSApp
::$db->query("SELECT * FROM " . TABLE_PREFIX
. "bugfield");
505 foreach ($fields_fetch as $field)
509 $fieldsPerm[$field['fieldid']] = $field;
513 $fields[$field['fieldid']] = $field;
520 /*=====================================================================*\
521 || ###################################################################
524 || ###################################################################
525 \*=====================================================================*/