--- layout: post title: "Simple Bugzilla client" date: 2011-04-23 comments: false categories: - bugzilla - development - consultancy - php - object orientation --- <div class='post'> At the moment I work as an IT Consultant on a QA-related project in Beijing at an outsourced partner. As you might know, the Internet connectivity in China is not optimal and this caused some issues on our end. Since we have to do a lot of cross-checking, we needed a way to keep track of remotely reported bugs and store these in a local instance of a previously in-house developed cross-check tracker. I started to develop a simple client to pull information from the remote Bugzilla instance which is then stored locally. This solved most of the issues we encountered with the latency and improved the productivity of our team.<br /><br /><b>XML-RPC client</b><br />The local tracker is built in PHP, so at first a small prototype was built to see if it was possible to call <a href="http://www.bugzilla.org/docs/3.6/en/html/api/Bugzilla/WebService/Server/XMLRPC.html">Bugzilla's XML-RPC interface</a>. To ease the development I chose to use the standard ZendFramework library and the XML-RPC client they offer, <a href="http://framework.zend.com/manual/en/zend.xmlrpc.client.html">Zend_XmlRpc_Client</a>. 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:<br /><br /><div style="color: white; background: none repeat scroll 0% 0% black;"><pre>// Add the AutoLoader<br />require_once('Zend/Loader/Autoloader.php');<br />Zend_Loader_Autoloader::getInstance();<br /><br />class BugzillaClient<br />{<br /> // Initialize the client<br /> protected $rpcClient = null;<br /> protected $basUrl = null;<br /><br /> public function __construct($baseUrl, $username, $password)<br /> {<br /> $this->baseUrl = $baseUrl; // Store internal for later use<br /> $this->rpcClient = new Zend_XmlRpc_Client($baseUrl . "/xmlrpc.cgi");<br /><br /> $httpClient = $this->rpcClient->getHttpClient();<br /> $httpClient->setCookieJar(); // Needed to retain user cookie<br /> $httpClient->setAuth($username, $password, Zend_Http_Client::AUTH_BASIC);<br /><br /> // Login request (XMLRPC)<br /> $response = $this->rpcClient->call('User.login', array(array(<br /> 'login' => $username,<br /> 'password' => $password,<br /> 'remember' => 1<br /> )));<br /> }<br /><br /> public function __destruct()<br /> {<br /> // Logout request (XMLRPC)<br /> $response = $this->rpcClient->call('User.logout', array());<br /> }<br /><br /> public function Get($id)<br /> {<br /> $returnValue = array();<br /><br /> // Get request (XMLRPC)<br /> $response = $this->rpcClient->call('Bug.get', array(array('ids' => $id)));<br /> $index = 0; // Only retrieving one bug, so don't bother with index now<br /><br /> $returnValue['id'] = $id;<br /> // Construct a remote URL<br /> $returnValue['url'] = $this->baseUrl . "/show_bug.cgi?id=" . $id;<br /> // Collect some basic information about the bug<br /> $returnValue['summary'] = $response['bugs'][$index]['summary'];<br /> $returnValue['status'] = $response['bugs'][$index]['status'];<br /> $returnValue['resolution'] = $response['bugs'][$index]['resolution'];<br /><br /> // Comments request (XMLRPC)<br /> $response = $this->rpcClient->call('Bug.comments', array(array('ids' => $id)));<br /> // Extract the first comment from the bug and store as description<br /> $returnValue['description'] = $response['bugs'][$id]['comments'][0]['text'];<br /><br /> return $returnValue;<br /> }<br />}<br /></pre></div><br />This <a href="https://github.com/gbraad/bugzilla-client/blob/master/PHP/BugzillaClient.php">code</a> provides a constructor which does the login and a 'Get' function to query the remote instance.<br /><br /><b>Example</b><br />To use this client you just need to include this module and create a new BugzillaClient instance.<br /><div style="color: white; background: none repeat scroll 0% 0% black;"><pre>require_once('config.php'); // Contains the baseUrl and credentials<br />require_once('BugzillaClient.php'); // This is the client code<br /><br />$bzClient = new BugzillaClient($bzBaseUrl, $bzUsername, $bzPassword);<br />$bug = $bzClient->Get($id);<br /><br />echo $bug['summary']);<br /></pre></div>After this the summary will be printed.<br /><span style="font-weight: bold;"></span><br /><span style="font-weight: bold;">Future work</span><br />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.<br /><br />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.<br /><br /><b>Repositories</b><br /><ul><li><a href="https://github.com/gbraad/bugzilla-client/">github</a></li><li><a href="https://gitorious.org/bugzilla-client/bugzilla-client/">gitorious</a></li></ul></div>