Permalink
Browse files

Big refactoring.

* Better code
* Caching
* Uses job queue to pull from bugzilla
  • Loading branch information...
1 parent 274ea29 commit b62c6d906285252dc9deeb1ac93078e550ff5895 @LegNeato LegNeato committed Aug 9, 2011
Showing with 450 additions and 138 deletions.
  1. +1 −0 .gitignore
  2. +27 −123 Bugzilla.class.php
  3. +50 −14 Bugzilla.php
  4. +74 −0 BugzillaJob.class.php
  5. +86 −0 BugzillaOutput.class.php
  6. +205 −0 BugzillaQuery.class.php
  7. +6 −0 cache.sql
  8. +1 −1 templates/bug/table.tpl
View
@@ -0,0 +1 @@
+*.swp
View
@@ -1,148 +1,52 @@
<?php
-require_once 'HTTP/Request2.php';
-require_once('smarty/Smarty.class.php');
-require_once(dirname(__FILE__) . '/Utils.php');
+require_once(dirname(__FILE__) . '/BugzillaOutput.class.php');
+// Factory
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 ) {
-
+ public static function create($config=array(), $opts=array(), $title='') {
// Default configuration
- // TODO: This should be in the main configuration
- $this->config = array(
+ // FIXME: This should be in the main configuration
+ $theconfig = 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;
+ $theconfig[$key] = $value;
}
- // Now that we have the data, process it
- $this->_process_data();
-
- }
-
- private function _process_data() {
- // TODO: Stub
- }
-
- public function render() {
+ // Generate the proper object
+ switch( $theconfig['display'] ) {
+ case 'list':
+ $b = new BugzillaList($theconfig, $opts, $title);
+ break;
- global $wgBugzillaSmartyTemplateDir;
- global $wgBugzillaSmartyCompileDir;
- global $wgBugzillaSmartyConfigDir;
- global $wgBugzillaSmartyCacheDir;
-
- // If we have an error, render it out instead
- if( $this->error ) {
- return $this->_render_error();
- }
+ case 'bar':
+ $b = new BugzillaBarGraph($theconfig, $opts, $title);
+ break;
- // 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;
+ case 'vbar':
+ $b = new BugzillaVerticalBarGraph($theconfig, $opts, $title);
+ break;
+ case 'pie':
+ $b = new BugzillaPieGraph($theconfig, $opts, $title);
+ break;
- // 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');
+ case 'inline':
+ $b = new BugzillaInline($theconfig, $opts, $title);
+ break;
- 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');
+ case 'table':
+ default:
+ $b = new BugzillaTable($theconfig, $opts, $title);
}
- }
+ return $b;
- private function _render_error() {
- $what = (!empty($this->error)) ? $this->error : 'Unknown Error';
- return "<div class='bugzilla error'>Bugzilla Error: $what</div>";
}
-
}
-
-
?>
View
@@ -1,6 +1,5 @@
<?php
-
// -----------------------------------------------------------------------------
// Extension credits / metadata
// -----------------------------------------------------------------------------
@@ -19,19 +18,59 @@
// -----------------------------------------------------------------------------
// Register the classes to autoload
-$wgAutoloadClasses['Bugzilla'] = dirname(__FILE__) . '/Bugzilla.class.php';
+$wgAutoloadClasses['Bugzilla'] = dirname(__FILE__) .
+ '/Bugzilla.class.php';
+$wgAutoloadClasses['BugzillaQuery'] = dirname(__FILE__) .
+ '/BugzillaQuery.class.php';
+$wgAutoloadClasses['BugzillaOutput'] = dirname(__FILE__) .
+ '/BugzillaOutput.class.php';
+$wgAutoloadClasses['BugzillaJob'] = dirname(__FILE__) .
+ '/BugzillaJob.class.php';
+
+// -----------------------------------------------------------------------------
+// Register our background job
+// -----------------------------------------------------------------------------
+
+$wgJobClasses['queryBugzillaUpdate'] = 'BugzillaUpdateJob';
+$wgJobClasses['queryBugzillaInsert'] = 'BugzillaInsertJob';
+
// -----------------------------------------------------------------------------
// Register for MediaWiki hooks
// -----------------------------------------------------------------------------
-$wgHooks['BeforePageDisplay'][] = 'BugzillaIncludeHTML';
-$wgHooks['ParserFirstCallInit'][] = 'BugzillaParserInit';
+$wgHooks['LoadExtensionSchemaUpdates'][] = 'BugzillaCreateCache';
+$wgHooks['BeforePageDisplay'][] = 'BugzillaIncludeHTML';
+$wgHooks['ParserFirstCallInit'][] = 'BugzillaParserInit';
// -----------------------------------------------------------------------------
// Hook work functions
// -----------------------------------------------------------------------------
+// Schema updates for the database cache
+function BugzillaCreateCache( $updater ) {
+ if( $updater === null ) {
+ // <= 1.16 support
+ global $wgExtNewTables;
+ global $wgExtModifiedFields;
+ $wgExtNewTables[] = array(
+ 'bugzilla_cache',
+ dirname( __FILE__ ) . '/cache.sql'
+ );
+ }else {
+ // >= 1.17 support
+ $updater->addExtensionUpdate( array( 'addTable',
+ 'bugzilla_cache',
+ dirname( __FILE__ ) . '/cache.sql',
+ TRUE )
+ );
+ }
+
+ // Let the other hooks keep processing
+ return TRUE;
+}
+
+// Add content to page HTML
function BugzillaIncludeHTML( &$out, &$sk ) {
global $wgScriptPath;
@@ -58,12 +97,11 @@ function BugzillaIncludeHTML( &$out, &$sk ) {
// Add the script to do table magic
$out->addInlineScript('$(document).ready(function() {
$(".bugzilla").dataTable({
- "bJQueryUI": true,
- "sPaginationType": "full_numbers"
+ "bJQueryUI": true
})});');
// Let the other hooks keep processing
- return true;
+ return TRUE;
}
// Hook our callback function into the parser
@@ -74,7 +112,7 @@ function BugzillaParserInit( Parser &$parser ) {
$parser->setHook( $wgBugzillaTagName, 'BugzillaRender' );
// Let the other hooks keep processing
- return true;
+ return TRUE;
}
// Function to be called when our tag is found by the parser
@@ -86,12 +124,9 @@ function BugzillaRender($input, array $args, Parser $parser ) {
$parser->disableCache();
// Create a new bugzilla object
- $bz = new Bugzilla($wgBugzillaRESTURL, $args);
-
- // Talk to bugzilla
- $bz->fetch($input);
+ $bz = Bugzilla::create($args, $input, $parser->getTitle());
- // Show the results (or an error if there was one)
+ // Show the desired output (or an error if there was one)
return $bz->render();
}
@@ -103,6 +138,7 @@ function BugzillaRender($input, array $args, Parser $parser ) {
$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;
$wgBugzillaJqueryTable = FALSE;
@@ -114,4 +150,4 @@ function BugzillaRender($input, array $args, Parser $parser ) {
$wgBugzillaSmartyConfigDir = dirname(__FILE__) . '/configs/';
$wgBugzillaSmartyCacheDir = '/tmp/';
-?>
+
View
@@ -0,0 +1,74 @@
+<?php
+
+abstract class BugzillaJob extends Job {
+
+ // Run the job
+ public function run() {
+
+ $this->query = unserialize($this->params['query_obj']);
+ $article = new Article( $this->title );
+
+ if( $article ) {
+
+ // Pull from Bugzilla
+ $this->query->_fetch_by_options();
+
+ // Mess with the database
+ $this->_database_work();
+
+ }
+
+ return TRUE;
+ }
+
+}
+
+class BugzillaInsertJob extends BugzillaJob {
+ // Set up the background job
+ public function __construct( $title, $params ) {
+ parent::__construct('queryBugzillaInsert', $title, $params );
+ }
+
+ public function _database_work() {
+
+ // Get the master because we are writing
+ $dbw = wfGetDB( DB_MASTER );
+
+ // Add it to the cache
+ $res = $dbw->insert(
+ 'bugzilla_cache',
+ array('id' => $this->query->id(),
+ 'fetched_at' => wfTimestamp(TS_DB),
+ 'data' => serialize($this->query->data)),
+ __METHOD__
+ );
+
+ }
+
+}
+
+class BugzillaUpdateJob extends BugzillaJob {
+ // Set up the background job
+ public function __construct( $title, $params ) {
+ parent::__construct('queryBugzillaUpdate', $title, $params );
+ }
+
+ public function _database_work() {
+
+ // Get the master because we are writing
+ $dbw = wfGetDB( DB_MASTER );
+
+ // Update cache entry
+ $res = $dbw->update(
+ 'bugzilla_cache',
+ array('id' => $this->query->id(),
+ 'fetched_at' => wfTimestamp(TS_DB),
+ 'data' => serialize($this->query->data)),
+ array('id' => $this->query->id()),
+ __METHOD__
+ );
+
+ }
+}
+
+?>
Oops, something went wrong.

0 comments on commit b62c6d9

Please sign in to comment.