Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix support for jquery tables, add the ability to specify fields,

refactor templates, add support for a simple HTML list output type, add
some CSS classes for bugs in various states, ignore all sorts of
swap files in the .gitignore
  • Loading branch information...
commit 5a4db4a462ea41984ffdf306d5a732204c62349e 1 parent 060a430
@LegNeato LegNeato authored
View
2  .gitignore
@@ -1 +1 @@
-*.swp
+*.sw*
View
43 Bugzilla.php
@@ -74,12 +74,14 @@ function BugzillaCreateCache( $updater ) {
function BugzillaIncludeHTML( &$out, &$sk ) {
global $wgScriptPath;
+ global $wgBugzillaJqueryTable;
- // Use local jquery
- $out->addScriptFile("$wgScriptPath/extensions/Bugzilla/web/jquery/1.6.2/jquery.min.js");
+ if( $wgBugzillaJqueryTable ) {
+ // Use local jquery
+ $out->addScript("<script type='text/javascript' src='$wgScriptPath/extensions/Bugzilla/web/jquery/1.6.2/jquery.min.js'></script>");
- // Use local jquery ui
- $out->addScriptFile("$wgScriptPath/extensions/Bugzilla/web/jqueryui/1.8.14/jquery-ui.min.js");
+ // Use local jquery ui
+ $out->addScript("<script type='text/javascript' src='$wgScriptPath/extensions/Bugzilla/web/jqueryui/1.8.14/jquery-ui.min.js'></script>");
// Add a local script file for the datatable
$out->addScriptFile("$wgScriptPath/extensions/Bugzilla/web/js/jquery.dataTables.js");
@@ -96,9 +98,18 @@ function BugzillaIncludeHTML( &$out, &$sk ) {
// Add the script to do table magic
$out->addInlineScript('$(document).ready(function() {
- $(".bugzilla").dataTable({
+ $("table.bugzilla").dataTable({
"bJQueryUI": true
})});');
+ }
+
+ // Add local bugzilla extension styles
+ $out->addStyle("$wgScriptPath/extensions/Bugzilla/web/css/bugzilla.css");
+
+ // Let the user optionally override bugzilla extension styles
+ if( file_exists("$wgScriptPath/extensions/Bugzilla/web/css/custom.css") ) {
+ $out->addStyle("$wgScriptPath/extensions/Bugzilla/web/css/custom.css");
+ }
// Let the other hooks keep processing
return TRUE;
@@ -122,7 +133,13 @@ function BugzillaRender($input, array $args, Parser $parser, $frame ) {
// We don't want the page to be cached
// TODO: Not sure if we need this
$parser->disableCache();
- $input = $parser->recursiveTagParse($input, $frame);
+
+ // TODO: Figure out to have the parser not do anything to our output
+ // mediawiki docs are wrong :-(
+ // error_log(print_r($parser->mStripState, true));
+ // $parser->mStripState->addItem( 'nowiki', 'NOWIKI', true);
+ // 'noparse' => true, 'isHTML' => true, 'markerType' => 'nowiki' );
+
// Create a new bugzilla object
$bz = Bugzilla::create($args, $input, $parser->getTitle());
@@ -138,13 +155,19 @@ function BugzillaRender($input, array $args, Parser $parser, $frame ) {
$wgBugzillaRESTURL = 'https://api-dev.bugzilla.mozilla.org/latest';
$wgBugzillaURL = 'https://bugzilla.mozilla.org';
$wgBugzillaTagName = 'bugzilla';
-$wgBugzillaMethod = 'REST'; // XML-RPC and JSON-RPC may be supported later
-$wgBugzillaUseCache = TRUE;
-$wgBugzillaCacheMins = 5;
+$wgBugzillaMethod = 'REST'; // XML-RPC and JSON-RPC aren't supported yet
+$wgBugzillaDefaultFields = array(
+ 'id',
+ 'summary',
+ 'priority',
+ 'status',
+);
$wgBugzillaJqueryTable = FALSE;
// Cache settings
-$wgCacheObject = 'BugzillaCacheMysql';
+$wgBugzillaUseCache = TRUE;
+$wgCacheObject = 'BugzillaCacheDummy';
+$wgBugzillaCacheMins = 10;
$wgBugzillaChartStorage = realpath($cwd . '/charts');
$wgBugzillaFontStorage = $cwd . '/pchart/fonts';
View
57 BugzillaOutput.class.php
@@ -6,8 +6,8 @@
public $cache;
public function __construct($config, $options, $title='') {
- $this->title = $title;
- $this->config = $config;
+ $this->title = $title;
+ $this->config = $config;
$this->error = FALSE;
$this->response = new stdClass();
@@ -64,20 +64,53 @@ protected function _getCache()
return $this->cache;
}
-
- abstract public function _setup_template_data();
+
+ abstract protected function _setup_template_data();
}
-class BugzillaTable extends BugzillaOutput {
+class BugzillaBugListing extends BugzillaOutput {
+
+ protected function _setup_template_data() {
- public function _setup_template_data() {
- if(count($this->query->data->bugs) > 0) {
- $this->response->bugs = $this->query->data->bugs;
- } else {
- $this->response->bugs = array();
+ global $wgBugzillaDefaultFields;
+
+ $this->response->bugs = array();
+ $this->response->fields = array();
+
+ // Set the bug data for the templates
+ if(count($this->query->data['bugs']) > 0) {
+ $this->response->bugs = $this->query->data['bugs'];
+ }
+
+ // Set the field data for the templates
+ if( isset($this->query->options['include_fields']) &&
+ !empty($this->query->options['include_fields']) ) {
+ // User specified some fields
+ $tmp = @explode(',', $this->query->options['include_fields']);
+ foreach( $tmp as $tmp_field ) {
+ $field = trim($tmp_field);
+ // Catch if the user specified the same field multiple times
+ if( !empty($field) &&
+ !in_array($field, $this->response->fields) ) {
+ array_push($this->response->fields, $field);
+ }
+ }
+ }else {
+ // If the user didn't specify any fields in the query config use
+ // default fields
+ $this->response->fields = $wgBugzillaDefaultFields;
}
}
+
+}
+
+class BugzillaList extends BugzillaBugListing {
+
+}
+
+class BugzillaTable extends BugzillaBugListing {
+
}
abstract class BugzillaGraph extends BugzillaOutput {
@@ -94,9 +127,9 @@ public function generate_chart($chart_name)
{
global $wgBugzillaChartStorage, $wgBugzillaFontStorage;
$pData = new pData();
- $pData->addPoints($this->query->data->data, 'Counts');
+ $pData->addPoints($this->query->data['data'], 'Counts');
$pData->setAxisName(0, 'Bugs');
- $pData->addPoints($this->query->data->x_labels, "Bugs");
+ $pData->addPoints($this->query->data['x_labels'], "Bugs");
$pData->setSerieDescription("Bugs", "Bugs");
$pData->setAbscissa("Bugs");
View
77 BugzillaQuery.class.php
@@ -21,14 +21,15 @@ public function create($type, $options, $title) {
abstract class BugzillaBaseQuery {
public function __construct($type, $options, $title) {
- $this->type = $type;
- $this->title = $title;
- $this->url = FALSE;
- $this->id = FALSE;
- $this->fetched_at = FALSE;
- $this->error = FALSE;
- $this->data = array();
- $this->cache = FALSE;
+ $this->type = $type;
+ $this->title = $title;
+ $this->url = FALSE;
+ $this->id = FALSE;
+ $this->fetched_at = FALSE;
+ $this->error = FALSE;
+ $this->data = array();
+ $this->synthetic_fields = array();
+ $this->cache = FALSE;
$this->_set_options($options);
}
@@ -59,10 +60,43 @@ protected function _generate_id() {
// Sort it so the keys are always in the same order
ksort($this->options);
+
+ // Treat include_fields special because we don't want to query multiple
+ // times if the same fields were requested in a different order
+ $saved_include_fields = array();
+ if( isset($this->options['include_fields']) &&
+ !empty($this->options['include_fields']) ) {
+
+ $saved_include_fields = $this->options['include_fields'];
+
+ // This is important. If a user asks for a subset of the default
+ // fields and another user has the same query w/ a subset,
+ // it is silly to cache the queries separately. We know the
+ // defaults will always be pulled, so anything asking for
+ // any combination of the defaults (or any combined subset) are
+ // esentially the same
+ $include_fields = $this->synthetic_fields;
+
+ $tmp = @explode(',', $this->options['include_fields']);
+ foreach( $tmp as $tmp_field ) {
+ $field = trim($tmp_field);
+ // Catch if the user specified the same field multiple times
+ if( !empty($field) && !in_array($field, $include_fields) ) {
+ array_push($include_fields, $field);
+ }
+ }
+ sort($include_fields);
+ $this->options['include_fields'] = @implode(',', $include_fields);
+ }
// Get a string representation of the array
$id_string = serialize($this->options);
+ // Restore the include_fields to what the user wanted
+ if( $saved_include_fields ) {
+ $this->options['include_fields'] = $saved_include_fields;
+ }
+
// Hash it
$this->id = sha1($id_string);
@@ -108,13 +142,11 @@ public function fetch() {
protected function _set_options($query_options_raw) {
// Make sure query options are valid JSON
- $this->options = json_decode($query_options_raw);
+ $this->options = json_decode($query_options_raw, TRUE);
if( !$query_options_raw || !$this->options ) {
$this->error = 'Query options must be valid json';
return;
}
- // Object is kinda useless, make it an array
- $this->options = get_object_vars($this->options);
}
abstract public function _fetch_by_options();
@@ -131,6 +163,7 @@ class BugzillaRESTQuery extends BugzillaBaseQuery {
function __construct($type, $options, $title='') {
global $wgBugzillaRESTURL;
+ global $wgBugzillaDefaultFields;
parent::__construct($type, $options, $title);
@@ -138,14 +171,17 @@ function __construct($type, $options, $title='') {
switch( $type ) {
// Whitelist
- case 'bug':
case 'count':
$this->url = $wgBugzillaRESTURL . '/' . urlencode($type);
+ // Note there are no synthetic fields for count
break;
// Default to a bug query
+ case 'bug':
default:
$this->url = $wgBugzillaRESTURL . '/bug';
+ // Even if the user didn't specify, we need these
+ $this->synthetic_fields = $wgBugzillaDefaultFields;
}
$this->fetch();
@@ -165,15 +201,28 @@ public function _fetch_by_options() {
$request->setHeader('Accept', 'application/json');
$request->setHeader('Content-Type', 'application/json');
- // Add in the requested query options
+ // Save the real options
+ $saved_options = $this->options;
+
+ // Add any synthetic fields to the options
+ if( !empty($this->synthetic_fields) ) {
+ $this->options['include_fields'] =
+ @array_merge((array)$this->options['include_fields'],
+ $this->synthetic_fields);
+ }
+
+ // Add the requested query options to the request
$url = $request->getUrl();
$url->setQueryVariables($this->options);
+ // Retore the real options, removing anything we synthesized
+ $this->options = $saved_options;
+
// This is basically straight from the HTTP/Request2 docs
try {
$response = $request->send();
if (200 == $response->getStatus()) {
- $this->data = json_decode($response->getBody());
+ $this->data = json_decode($response->getBody(), TRUE);
} else {
$this->error = 'Server returned unexpected HTTP status: ' .
$response->getStatus() . ' ' .
View
36 templates/bug/list.tpl
@@ -0,0 +1,36 @@
+<ul class="bugzilla ui-helper-reset">
+ <?php
+ $base = dirname(__FILE__) . '/../../templates/fields/';
+
+ foreach( $response->bugs as $bug ) {
+ echo "<li class='bugzilla-status-${bug['status']}'>";
+ $count = 0;
+ foreach( $response->fields as $field ) {
+ if( $count ) {
+ echo " - ";
+ }
+ echo "<span class='bugzilla-data-$field'>";
+
+ // Get our template path
+ $subtemplate = $base .
+ escapeshellcmd(str_replace('..',
+ 'DOTS',
+ $field)) .
+ '.tpl';
+
+ // Make sure a template is there
+ if( !file_exists($subtemplate) ) {
+ $subtemplate = $base . '_default.tpl';
+ }
+
+ // Print out the data
+ $data = $bug[$field];
+ require($subtemplate);
+
+ echo "</span>";
+ $count++;
+ }
+ echo "</li>\n";
+ }
+ ?>
+</ul>
View
64 templates/bug/table.tpl
@@ -1,20 +1,58 @@
-<table class="bugzilla ui-helper-reset">
+<?php
+ global $wgBugzillaJqueryTable;
+ $extra_class = ($wgBugzillaJqueryTable) ? 'jquery ui-helper-reset' : '';
+?>
+<table class="bugzilla <?php echo $extra_class ?>">
<thead>
<tr>
- <th>ID</th>
- <th>Summary</th>
- <th>Status</th>
- <th>Priority</th>
+ <?php
+ foreach( $response->fields as $field ) {
+ echo "<th>";
+ switch( $field ) {
+ case 'id':
+ echo 'ID';
+ break;
+ default:
+ echo htmlspecialchars(
+ ucfirst(
+ str_replace('_', ' ',
+ preg_replace('/^cf_/', '',
+ $field))));
+ }
+ echo "</th>\n";
+ }
+ ?>
</tr>
</thead>
<tbody>
- <?php foreach($response->bugs as $bug): ?>
- <tr>
- <td><a href="<?php echo $wgBugzillaURL ?>/show_bug.cgi?id=<?php echo $bug->id ?>"><?php echo $bug->id ?></a></td>
- <td><a href="<?php echo $wgBugzillaURL ?>/show_bug.cgi?id=<?php echo $bug->id ?>"><?php echo $bug->summary ?></a></td>
- <td><?php echo $bug->status ?></td>
- <td><?php echo $bug->priority ?></td>
- </tr>
- <?php endforeach; ?>
+ <?php
+ $base = dirname(__FILE__) . '/../../templates/fields/';
+
+ foreach( $response->bugs as $bug ) {
+ echo "<tr class='bugzilla-status-${bug['status']}'>";
+ foreach( $response->fields as $field ) {
+ echo "<td class='bugzilla-data-$field'>";
+
+ // Get our template path
+ $subtemplate = $base .
+ escapeshellcmd(str_replace('..',
+ 'DOTS',
+ $field)) .
+ '.tpl';
+
+ // Make sure a template is there
+ if( !file_exists($subtemplate) ) {
+ $subtemplate = $base . '_default.tpl';
+ }
+
+ // Print out the data
+ $data = $bug[$field];
+ require($subtemplate);
+
+ echo "</td>\n";
+ }
+ echo "</tr>\n";
+ }
+ ?>
</tbody>
</table>
View
5 templates/fields/_default.tpl
@@ -0,0 +1,5 @@
+<?php
+ echo "<span class='bugzilla-field-$field'>";
+ echo htmlspecialchars($bug[$field]);
+ echo "</span>";
+?>
View
8 templates/fields/id.tpl
@@ -0,0 +1,8 @@
+<?php
+ global $wgBugzillaURL;
+
+ echo "<a href='$wgBugzillaURL/show_bug.cgi?id=" .
+ urlencode($bug['id']) ."'>";
+ echo htmlspecialchars($bug['id']);
+ echo "</a>";
+?>
View
8 templates/fields/summary.tpl
@@ -0,0 +1,8 @@
+<?php
+ global $wgBugzillaURL;
+
+ echo "<a href='$wgBugzillaURL/show_bug.cgi?id=" .
+ urlencode($bug['id']) ."'>";
+ echo htmlspecialchars($bug['summary']);
+ echo "</a>";
+?>
View
8 templates/fields/url.tpl
@@ -0,0 +1,8 @@
+<?php
+ global $wgBugzillaURL;
+
+ echo "<a href='$wgBugzillaURL/show_bug.cgi?id=" .
+ urlencode($bug['id']) ."'>";
+ echo htmlspecialchars($bug['url']);
+ echo "</a>";
+?>
View
33 web/css/bugzilla.css
@@ -1,5 +1,32 @@
-/*
-table.bugzilla {
+
+/* Jquery table */
+table.jquery.bugzilla {
width: 100%;
}
-*/
+
+/* Table view styles */
+
+tr.bugzilla-status-NEW {
+ background-color: #ffeeee;
+}
+
+tr.bugzilla-status-ASSIGNED {
+ background-color: #eeeeff;
+}
+
+tr.bugzilla-status-REOPENED {
+ background-color: #ffffee;
+}
+
+tr.bugzilla-status-RESOLVED {
+ background-color: #eeffee;
+}
+
+tr.bugzilla-status-VERIFIED {
+ background-color: #ccffcc;
+
+/* General styles */
+.bugzilla-status-RESOLVED .bugzilla-data-id,
+.bugzilla-status-VERIFIED .bugzilla-data-id {
+ text-decoration: line-through;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.