Permalink
Browse files

Initial upload to GitHub

  • Loading branch information...
LegNeato committed Jul 28, 2011
0 parents commit 8590a4fc09c423fcd947d1b95b6ec3323eecddd3
@@ -0,0 +1,148 @@
+<?php
+
+require_once 'HTTP/Request2.php';
+require_once('smarty/Smarty.class.php');
+require_once(dirname(__FILE__) . '/Utils.php');
+
+class Bugzilla {
+
+ // Set variables and initialize the backend
+ function __construct($url, $config=array(), $id=FALSE) {
+ $this->url = $url;
+ $this->id = $id;
+ $this->error = FALSE;
+ $this->data = FALSE;
+
+ $this->_configure($config);
+ }
+
+ private function _configure( $config ) {
+
+ // Default configuration
+ // TODO: This should be in the main configuration
+ $this->config = array(
+ 'type' => 'bug',
+ 'display' => 'table',
+ );
+
+ // Overlay user's desired configuration
+ foreach( $config as $key => $value ) {
+ $this->config[$key] = $value;
+ }
+ }
+
+ // Connect and get the data
+ public function fetch( $query_opts_raw = FALSE ) {
+
+ // Don't do anything if we already had an error
+ if( $this->error ) { return; }
+
+ // TODO: To support loading from the DB in the future
+ if( $this->id ) {
+ $this->_fetch_by_id();
+ return;
+ }
+
+ // Make sure query options are valid JSON
+ $opts = json_decode($query_opts_raw);
+ if( !$query_opts_raw || !$opts ) {
+ $this->error = 'Query options must be valid json';
+ return;
+ }
+
+ // Do the actual fetching
+ $this->_fetch_by_options($opts);
+ }
+
+ private function _fetch_by_id() {
+ // TODO: Stub
+ }
+
+ // Load data from the Bugzilla REST API
+ private function _fetch_by_options($opts) {
+
+ // Set up our HTTP request
+ $request = new HTTP_Request2($this->url . "/" . $this->config['type'],
+ HTTP_Request2::METHOD_GET,
+ array('follow_redirects' => TRUE,
+ // TODO: Not sure if I should do this
+ 'ssl_verify_peer' => FALSE));
+
+ // The REST API requires these
+ $request->setHeader('Accept', 'application/json');
+ $request->setHeader('Content-Type', 'application/json');
+
+ // Add in the requested query options
+ $url = $request->getUrl();
+ $url->setQueryVariables(get_object_vars($opts));
+
+ // This is basically straight from the HTTP/Request2 docs
+ try {
+ $response = $request->send();
+ if (200 == $response->getStatus()) {
+ $this->data = json_decode($response->getBody());
+ } else {
+ $this->error = 'Server returned unexpected HTTP status: ' .
+ $response->getStatus() . ' ' .
+ $response->getReasonPhrase();
+ return;
+ }
+ } catch (HTTP_Request2_Exception $e) {
+ $this->error = $e->getMessage();
+ return;
+ }
+
+ // Now that we have the data, process it
+ $this->_process_data();
+
+ }
+
+ private function _process_data() {
+ // TODO: Stub
+ }
+
+ public function render() {
+
+ global $wgBugzillaSmartyTemplateDir;
+ global $wgBugzillaSmartyCompileDir;
+ global $wgBugzillaSmartyConfigDir;
+ global $wgBugzillaSmartyCacheDir;
+
+ // If we have an error, render it out instead
+ if( $this->error ) {
+ return $this->_render_error();
+ }
+
+ // No error, we're good to go
+ $smarty = new Smarty();
+ $smarty->template_dir = $wgBugzillaSmartyTemplateDir;
+ $smarty->compile_dir = $wgBugzillaSmartyCompileDir;
+ $smarty->config_dir = $wgBugzillaSmartyConfigDir;
+ $smarty->cache_dir = $wgBugzillaSmartyCacheDir;
+
+
+ // TODO: This is basically a prototype, needs to be better
+ if( $this->config['display'] == 'table' ) {
+ $smarty->assign('bugs', $this->data->bugs);
+ return $smarty->fetch('bug/table.tpl');
+
+ elseif( $this->config['display'] == 'bar' ) {
+ $smarty->assign('type', 'bhs');
+ #$smarty->assign('type', 'p');
+ $smarty->assign('size', '200x300');
+ $smarty->assign('x_labels', implode('|', $this->data->x_labels));
+ $smarty->assign('data', implode(',', $this->data->data));
+ return $smarty->fetch('count/bar.tpl');
+ }
+
+ }
+
+ public function _render_error() {
+ $what = (!empty($this->error)) ? $this->error : 'Unknown Error';
+ return "<div class='bugzilla error'>Bugzilla Error: $what</div>";
+ }
+
+}
+
+
+?>
@@ -0,0 +1,117 @@
+<?php
+
+
+// -----------------------------------------------------------------------------
+// Extension credits / metadata
+// -----------------------------------------------------------------------------
+
+$wgExtensionCredits['other'][] = array(
+ 'name' => 'Bugzilla',
+ 'author' => 'Christian Legnitto',
+ 'url' => 'https://github.com/LegNeato/mediawiki-bugzilla',
+ 'description' => 'This extension allows read-only integration with '.
+ 'Bugzilla via the REST API',
+);
+
+
+// -----------------------------------------------------------------------------
+// General setup
+// -----------------------------------------------------------------------------
+
+// Register the classes to autoload
+$wgAutoloadClasses['Bugzilla'] = dirname(__FILE__) . '/Bugzilla.class.php';
+
+// -----------------------------------------------------------------------------
+// Register for MediaWiki hooks
+// -----------------------------------------------------------------------------
+
+$wgHooks['BeforePageDisplay'][] = 'BugzillaIncludeHTML';
+$wgHooks['ParserFirstCallInit'][] = 'BugzillaParserInit';
+
+// -----------------------------------------------------------------------------
+// Hook work functions
+// -----------------------------------------------------------------------------
+
+function BugzillaIncludeHTML( &$out, &$sk ) {
+
+ global $wgScriptPath;
+
+ // Use remote jquery
+ $out->addScript('<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>');
+
+ // Use remote jquery ui
+ $out->addScript('<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/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" );
+
+ // Add a remote jquery css file
+ $out->addStyle("http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/base/jquery-ui.css");
+
+ // Add a remote jquery UI theme css file
+ $out->addStyle("http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/smoothness/jquery-ui.css");
+
+ // Add local datatable styles
+ $out->addStyle("$wgScriptPath/extensions/Bugzilla/web/css/demo_page.css");
+ $out->addStyle("$wgScriptPath/extensions/Bugzilla/web/css/demo_table.css");
+
+ // Add the script to do table magic
+ $out->addInlineScript('$(document).ready(function() {
+ $(".bugzilla").dataTable({
+ "bJQueryUI": true,
+ "sPaginationType": "full_numbers"
+ })});');
+
+ // Let the other hooks keep processing
+ return true;
+}
+
+// Hook our callback function into the parser
+function BugzillaParserInit( Parser &$parser ) {
+ global $wgBugzillaTagName;
+
+ // Register the desired tag
+ $parser->setHook( $wgBugzillaTagName, 'BugzillaRender' );
+
+ // Let the other hooks keep processing
+ return true;
+}
+
+// Function to be called when our tag is found by the parser
+function BugzillaRender($input, array $args, Parser $parser ) {
+ global $wgBugzillaRESTURL;
+
+ // We don't want the page to be cached
+ // TODO: Not sure if we need this
+ $parser->disableCache();
+
+ // Create a new bugzilla object
+ $bz = new Bugzilla($wgBugzillaRESTURL, $args);
+
+ // Talk to bugzilla
+ $bz->fetch($input);
+
+ // Show the results (or an error if there was one)
+ return $bz->render();
+}
+
+
+// -----------------------------------------------------------------------------
+// Default configuration
+// -----------------------------------------------------------------------------
+
+$wgBugzillaRESTURL = 'https://api-dev.bugzilla.mozilla.org/latest';
+$wgBugzillaURL = 'https://bugzilla.mozilla.org';
+$wgBugzillaTagName = 'bugzilla';
+$wgBugzillaUseCache = TRUE;
+$wgBugzillaCacheMins = 5;
+$wgBugzillaJqueryTable = FALSE;
+
+// We use smarty...
+$wgBugzillaSmartyDir = '/usr/share/php/smarty/';
+$wgBugzillaSmartyTemplateDir = dirname(__FILE__) . '/templates/';
+$wgBugzillaSmartyCompileDir = '/tmp/';
+$wgBugzillaSmartyConfigDir = dirname(__FILE__) . '/configs/';
+$wgBugzillaSmartyCacheDir = '/tmp/';
+
+?>
@@ -0,0 +1,35 @@
+<?php
+
+
+function gChartExtendedEncode($arrVals, $maxVal) {
+// Same as simple encoding, but for extended encoding.
+ $EXTENDED_MAP=
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
+ $EXTENDED_MAP_LENGTH = strlen($EXTENDED_MAP);
+ $chartData = '';
+
+ for($i = 0, $len = count($arrVals); $i < $len; $i++) {
+ // In case the array vals were translated to strings.
+ $numericVal = $arrVals[$i];
+ // Scale the value to maxVal.
+ $scaledVal = floor($EXTENDED_MAP_LENGTH *
+ $EXTENDED_MAP_LENGTH * $numericVal / $maxVal);
+
+ if($scaledVal > ($EXTENDED_MAP_LENGTH * $EXTENDED_MAP_LENGTH) - 1) {
+ $chartData .= "..";
+ }elseif($scaledVal < 0) {
+ $chartData .= '__';
+ } else {
+ // Calculate first and second digits and add them to the output.
+ $quotient = floor($scaledVal / $EXTENDED_MAP_LENGTH);
+ $remainder = $scaledVal - $EXTENDED_MAP_LENGTH * $quotient;
+ $chartData .= $EXTENDED_MAP[$quotient] . $EXTENDED_MAP[$remainder];
+ }
+ }
+
+ return $chartData;
+}
+
+
+
+?>
@@ -0,0 +1,22 @@
+{* SMARTY *}
+
+<table class="bugzilla ui-helper-reset">
+ <thead>
+ <tr>
+ <th>ID</th>
+ <th>Summary</th>
+ <th>Status</th>
+ <th>Priority</th>
+ </tr>
+ </thead>
+ <tbody>
+ {foreach from=$bugs item=bug}
+ <tr>
+ <td>{$bug->id|escape}</td>
+ <td>{$bug->summary|escape}</td>
+ <td>{$bug->status|escape}</td>
+ <td>{$bug->priority|escape}</td>
+ </tr>
+ {/foreach}
+ </tbody>
+</table>
@@ -0,0 +1,2 @@
+{* SMARTY *}
+<img src="http://chart.apis.google.com/chart?cht={$type|escape:'url'}&chs={$size|escape:'url'}&chds=a&chd=t:{$data|escape:'url'}&chxl=1:|{$x_labels|default:''|escape:'url'}&chxt=x,y&chtt={$title|default:''|escape:'url'}" />
63 vim
@@ -0,0 +1,63 @@
+MediaWiki extension for Bugzilla
+================================
+
+This is a MediaWiki extension that provides read-only access to the
+[Bugzilla REST API](https://wiki.mozilla.org/Bugzilla:REST_API)
+
+__Please note that this isn't finished / ready for production yet!__
+
+Requirements
+================================
+
+* Requires HTTP_Request2 from PEAR
+* Requires the SMARTY template library installed
+
+Usage
+================================
+
+You use this extension in this way:
+
+ <bugzilla>
+ (JSON REST API query key/value pairs)
+ </bugzilla>
+
+An example:
+
+ <bugzilla>
+ {
+ "product": "Bugzilla",
+ "priority":"P1"
+ }
+ </bugzilla>
+
+For more details on how to query in various ways, see the documentation for
+the [Bugzilla REST API](https://wiki.mozilla.org/Bugzilla:REST_API)
+
+Note that the tag name defaults to "bugzilla" but is configurable.
+
+There is also __exploratory__ support for charting:
+
+ <bugzilla type="count" display="bar">
+ {
+ "product": "Bugzilla",
+ "priority": "P1",
+ "x_axis_field": "severity"
+ }
+ </bugzilla>
+
+Limitations
+================================
+
+* This extension (by design) is read-only
+* This extension currently queries as a public (not logged in) user
+* Charts are fairly hardcoded and don't work in many cases
+
+TODO
+================================
+
+# This is basically a prototype right now...needs to be cleaned up a lot
+# The JQuery UI table doesn't render correctly...make it better
+# Support more types of queries than just "bug" (the default)
+# Support more types of wiki display than just a bug table
+# Caching and cache invalidation for queries
+# Support charting as a 1st class citizen
@@ -0,0 +1,5 @@
+/*
+table.bugzilla {
+ width: 100%;
+}
+*/
Oops, something went wrong.

0 comments on commit 8590a4f

Please sign in to comment.