1<?php 2/** 3 * Copyright 2010 Yuri Timofeev tim4dev@gmail.com 4 * 5 * This is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This software is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this software. If not, see <http://www.gnu.org/licenses/>. 17 * 18 * @desc Gets information about bugs (with depends on) via XML-RPC Bugzilla::WebService 19 * @author Yuri Timofeev <tim4dev@gmail.com> 20 * @package bugzillaxmlrpc 21 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU Public License 22 * @syntax bugz#12345 23 * 24 */ 25 26// must be run within DokuWiki 27if(!defined('DOKU_INC')) die(); 28if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 29require_once(DOKU_PLUGIN.'syntax.php'); 30 31class syntax_plugin_bugzillaxmlrpc extends DokuWiki_Syntax_Plugin { 32 33 protected $curl_opt = array( 34 CURLOPT_POST => true, 35 CURLOPT_RETURNTRANSFER => true, 36 CURLOPT_HTTPHEADER => array( 'Content-Type: text/xml', 'charset=utf-8' ) 37 ); 38 39 protected $xml_data = array( 40 'remember' => 1 41 ); 42 43 protected $cookie_file; 44 45 46 function getInfo(){ 47 return array( 48 'author' => 'Yuri Timofeev', 49 'email' => 'tim4dev@gmail.com', 50 'date' => '2010-09-09', 51 'name' => 'bugzilla xml-rpc plugin', 52 'desc' => 'Gets information about bugs via XML-RPC Bugzilla::WebService', 53 'url' => 'http://www.dokuwiki.org/plugin:bugzillaxmlrpc', 54 ); 55 } 56 57 function getType() { return 'substition'; } 58 function getPType() { return 'normal'; } 59 function getSort() { return 777; } 60 61 function connectTo($mode) { 62 $this->Lexer->addSpecialPattern('bugz#[0-9]+', $mode, 'plugin_bugzillaxmlrpc'); 63 } 64 65 66 function myLogin() { 67 // Login and get cookie 68 // http://www.bugzilla.org/docs/3.2/en/html/api/Bugzilla/WebService/User.html 69 $this->xml_data['login'] = $this->getConf('login'); 70 $this->xml_data['password'] = $this->getConf('password'); 71 $ch = curl_init(); 72 curl_setopt_array($ch, $this->curl_opt); 73 $request = xmlrpc_encode_request('User.login', $this->xml_data); 74 curl_setopt($ch, CURLOPT_URL, $this->getConf('xmlrpc.cgi')); 75 curl_setopt($ch, CURLOPT_POSTFIELDS, $request); 76 curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie_file ); 77 $server_output = curl_exec($ch); 78 curl_close($ch); 79 $response = xmlrpc_decode($server_output); 80 if ( empty($response) ) { 81 @unlink($this->cookie_file); 82 return array(1, 'NULL', 'NULL'); 83 } 84 return array(0, $response['faultString'], $response['faultCode'], $response['id']); 85 } 86 87 88 /** 89 * Return: 90 * bug_id, summary, dependson, product, creation_ts, bug_status, deadline 91 */ 92 function myGetBugInfo($id) { 93 // Login and get bug info 94 // http://www.bugzilla.org/docs/3.2/en/html/api/Bugzilla/WebService/Bug.html 95 $this->xml_data['login'] = $this->getConf('login'); 96 $this->xml_data['password'] = $this->getConf('password'); 97 $ch = curl_init(); 98 curl_setopt_array($ch, $this->curl_opt); 99 $this->xml_data['ids'] = array($id); 100 $request = xmlrpc_encode_request("Bug.get", $this->xml_data); 101 curl_setopt($ch, CURLOPT_URL, $this->getConf('xmlrpc.cgi')); 102 curl_setopt($ch, CURLOPT_POSTFIELDS, $request); 103 curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie_file ); 104 $server_output = curl_exec($ch); 105 curl_close($ch); 106 107 $response = xmlrpc_decode($server_output); 108 if (xmlrpc_is_fault($response)) 109 return array(1, $response[faultString], $response[faultCode], $id); 110 $v = $response['bugs'][0]; 111 // Login and get Product info 112 list($error, $faultString, $faultCode, $product) = $this->myGetProductInfo($v['internals']['product_id']); 113 if ($error) 114 return array(1, $response[faultString], $response[faultCode], $id); 115 // return all data 116 return array(0, $response[faultString], $response[faultCode], 117 $id, 118 $v['summary'], 119 $v['dependson'], 120 $product, 121 $v['internals']['creation_ts'], 122 $v['internals']['bug_status'], 123 $v['internals']['deadline'] 124 ); 125 } 126 127 128 function myGetProductInfo($id) { 129 // Login and get Product info 130 $this->xml_data['login'] = $this->getConf('login'); 131 $this->xml_data['password'] = $this->getConf('password'); 132 $ch = curl_init(); 133 curl_setopt_array($ch, $this->curl_opt); 134 $this->xml_data['ids'] = array($id); 135 $request = xmlrpc_encode_request("Product.get", $this->xml_data); 136 curl_setopt($ch, CURLOPT_URL, $this->getConf('xmlrpc.cgi')); 137 curl_setopt($ch, CURLOPT_POSTFIELDS, $request); 138 curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie_file ); 139 $server_output = curl_exec($ch); 140 curl_close($ch); 141 142 $response = xmlrpc_decode($server_output); 143 if (xmlrpc_is_fault($response)) 144 return array(1, $response[faultString], $response[faultCode]); 145 return array(0, $response[faultString], $response[faultCode], $response['products'][0]['name']); 146 } 147 148 function myLogout() { 149 unlink($this->cookie_file); 150 } 151 152 153 function handle($match, $state, $pos, &$handler) { 154 preg_match('/^bugz#([0-9]+)/', $match, $submatch); 155 $ids = $submatch[1]; 156 $data_bugs = array(); // two-dimensional array 157 if (empty($ids)) { 158 $data_bugs[] = array('error' => 1, 'faultString' => 'Empty Id', 'faultCode' => 999, 'id' => 0); 159 $this->myLogout; 160 return array($data_bugs); 161 } 162 // Login and get cookie 163 $this->cookie_file = tempnam('', 'bugzillaxmlrpc'); 164 list($error, $faultString, $faultCode, $id) = $this->myLogin(); 165 if ($error) { 166 $data_bugs[] = array('error' => 1, 'faultString' => $faultString, 'faultCode' => $faultCode, 'id' => $id); 167 $this->myLogout; 168 return array($data_bugs); 169 } 170 // Login and get bug info 171 // return: bug_id, summary, dependson, product, creation_ts, bug_status, deadline 172 list($error, $faultString, $faultCode, $id, $summary, $dependson, $product, $creation_ts, $bug_status, $deadline) = $this->myGetBugInfo($ids); 173 if ($error) { 174 $data_bugs[] = array('error' => 1, 'faultString' => $faultString, 'faultCode' => $faultCode, 'id' => $id); 175 $this->myLogout; 176 return array($data_bugs); 177 } 178 $data_bugs[0] = array('error' => 0, 'faultString' => $faultString, 'faultCode' => $faultCode, 179 'id' => $id, 'summary' => $summary, 'dependson' => $dependson, 'product' => $product, 180 'creation_ts' => $creation_ts, 'bug_status' => $bug_status, 'deadline' => $deadline); 181 // Get info about dependencies bugs 182 foreach ($dependson as $dep) { 183 list($error, $faultString, $faultCode, $id, $summary, $dependson, $product, $creation_ts, $bug_status, $deadline) = $this->myGetBugInfo($dep); 184 $data_bugs[] = array('error' => 0, 'faultString' => $faultString, 'faultCode' => $faultCode, 185 'id' => $id, 'summary' => $summary, 'dependson' => $dependson, 'product' => $product, 186 'creation_ts' => $creation_ts, 'bug_status' => $bug_status, 'deadline' => $deadline); 187 } 188 // return all data 189 $this->myLogout; 190 return array($data_bugs); 191 } 192 193 194 function render($mode, &$renderer, $data) { 195 if($mode == 'xhtml'){ 196 $data0 = $data[0]; 197 $html_bug_all = '<ul>' . "\n"; 198 $i = 1; 199 foreach ($data0 as $v) { 200 $html_bug = ''; 201 if ( ($i == 2) ) 202 $html_bug_all .= '<ul>'; 203 $id = $v['id']; 204 if ($v['error']) { 205 $html_bug .= '<div class="li"><a href="' . 206 $this->getConf('url').$id. '" target="_blank" title="'. 207 $this->getLang('title').$id. '" class="interwiki iw_bug">'. 208 $this->getLang('bug').' #' .$id. '</a> <i>'. 209 $this->getLang('error_prefix').' : ' . $v['faultCode'] . ' - ' . $v['faultString'] . 210 '</i></div>'; 211 } else { 212 if ( ($v['bug_status'] == 'CLOSED') || ($v['bug_status'] == 'RESOLVED') ) { 213 $s1 = '<s>'; 214 $s2 = '</s>'; 215 } else { 216 $s1 = ''; 217 $s2 = ''; 218 } 219 220 $html_bug .= '<div class="li"><a href="' . 221 $this->getConf('url').$id. '" target="_blank" title="'. 222 $this->getLang('title').$id. '" class="interwiki iw_bug">'. 223 $this->getLang('bug').' #' .$id. '</a>'.$s1.'<i> '. 224 $v['product']. '</i> -> <b>'.$v['summary']. '</b>'. 225 ' ('. $this->getLang('opened').': '. $v['creation_ts'] .', '. 226 $this->getLang('bug_status').': '. $v['bug_status'] .', '. 227 $this->getLang('deadline').': '. $v['deadline']. 228 ') '.$s2. 229 '</div>'; 230 } 231 $html_bug_all .= '<li>'.$html_bug.'</li>' . "\n"; 232 $i++; 233 } // foreach 234 if ( $i > 1 ) 235 $html_bug_all .= '</ul>'; 236 $renderer->doc .= $html_bug_all . '</ul>'; 237 return true; 238 } 239 return false; 240 } 241 242 243} 244