XML-RPC client
The local tracker is built in PHP, so at first a small prototype was built to see if it was possible to call Bugzilla's XML-RPC interface. To ease the development I chose to use the standard ZendFramework library and the XML-RPC client they offer, Zend_XmlRpc_Client. The biggest issue I encountered was the way authentication was implemented on the remote side, but the actual client was simple and very easy to implement. The prototype was first done in a very sequential way... and eventually after a little bit of refactoring this is what remained:
// Add the AutoLoader
require_once('Zend/Loader/Autoloader.php');
Zend_Loader_Autoloader::getInstance();
class BugzillaClient
{
// Initialize the client
protected $rpcClient = null;
protected $basUrl = null;
public function __construct($baseUrl, $username, $password)
{
$this->baseUrl = $baseUrl; // Store internal for later use
$this->rpcClient = new Zend_XmlRpc_Client($baseUrl . "/xmlrpc.cgi");
$httpClient = $this->rpcClient->getHttpClient();
$httpClient->setCookieJar(); // Needed to retain user cookie
$httpClient->setAuth($username, $password, Zend_Http_Client::AUTH_BASIC);
// Login request (XMLRPC)
$response = $this->rpcClient->call('User.login', array(array(
'login' => $username,
'password' => $password,
'remember' => 1
)));
}
public function __destruct()
{
// Logout request (XMLRPC)
$response = $this->rpcClient->call('User.logout', array());
}
public function Get($id)
{
$returnValue = array();
// Get request (XMLRPC)
$response = $this->rpcClient->call('Bug.get', array(array('ids' => $id)));
$index = 0; // Only retrieving one bug, so don't bother with index now
$returnValue['id'] = $id;
// Construct a remote URL
$returnValue['url'] = $this->baseUrl . "/show_bug.cgi?id=" . $id;
// Collect some basic information about the bug
$returnValue['summary'] = $response['bugs'][$index]['summary'];
$returnValue['status'] = $response['bugs'][$index]['status'];
$returnValue['resolution'] = $response['bugs'][$index]['resolution'];
// Comments request (XMLRPC)
$response = $this->rpcClient->call('Bug.comments', array(array('ids' => $id)));
// Extract the first comment from the bug and store as description
$returnValue['description'] = $response['bugs'][$id]['comments'][0]['text'];
return $returnValue;
}
}
This code provides a constructor which does the login and a 'Get' function to query the remote instance.
Example
To use this client you just need to include this module and create a new BugzillaClient instance.
require_once('config.php'); // Contains the baseUrl and credentials
require_once('BugzillaClient.php'); // This is the client code
$bzClient = new BugzillaClient($bzBaseUrl, $bzUsername, $bzPassword);
$bug = $bzClient->Get($id);
echo $bug['summary']);
Future work
The last time I did some actual development with PHP was during PHP 3 and the move to PHP 4. At that moment I was not so happy with the Object Orientation model that the language offered. Luckily this improved a lot and hope this code testifies of that... as I have seen some horrific spaghetti code during these several days.
Using this solution does not provide a complete up-to-date picture of the bug, but this is not a problem to us. Besides, triggering a script which iterates over all local bugs and queries the remote state solved this issue. Some more features will be implemented, like searching for bugs and pushing comments back. This basic implementation code has been posted to public git repositories, so fork it and start pushing your improvements.
Repositories