*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
if (file_exists($autoload = __DIR__. '/vendor/autoload.php')) {
require_once $autoload;
} else {
// try from include path
require_once 'XML/RPC.php';
require_once 'class.Eventum_RPC.php';
}
/**
* All DokuWiki plugins to extend the parser/rendering mechanism
* need to inherit from this class
*/
class syntax_plugin_eventum extends DokuWiki_Syntax_Plugin {
/*
* keys that we use for caching, to avoid running out of memory when serializing
*/
static $cache_keys = array(
'iss_summary' => 'summary',
'sta_title' => 'status',
'sta_is_closed' => 'is_closed',
);
/**
* What kind of syntax are we?
*/
function getType() {
return 'substition';
}
/**
* Where to sort in?
*/
function getSort() {
return 290;
}
/**
* Connect pattern to lexer
*/
function connectTo($mode) {
$this->Lexer->addSpecialPattern('\[\[issue>.+?\]\]', $mode, 'plugin_eventum');
}
/**
* Handle the match
*/
function handle($match, $state, $pos, Doku_Handler $handler) {
$raw = $match = substr($match, 8, -2);
// extract title
list($match, $title) = explode('|', $match, 2);
// extract id
list($id, $attrs) = explode('&', $match, 2);
$data = array('raw' => $raw, 'id' => $id, 'attrs' => $attrs);
// set title only when specified to be able to make difference between empty and unset
if ($title !== null) {
$data['title'] = trim($title);
}
return $data;
}
function cache($id, $data = null) {
global $conf;
$cachefile = $conf['cachedir'].'/'.$this->getPluginName().'.cache';
// mode: get but no cachefile
if ($data === null && !file_exists($cachefile)) {
return null;
}
// read cache
$cache = array();
if (file_exists($cachefile)) {
$cache = unserialize(file_get_contents($cachefile));
}
// expire as long as page edit time to make page edit smooth but still
// have almost accurate data.
$mtime = time() - $conf['locktime'];
foreach ($cache as $i => $ent) {
if ($ent['mtime'] < $mtime) {
unset($cache[$i]);
}
}
// mode get:
if ($data === null) {
return isset($cache[$id]) ? $cache[$id] : null;
}
// mode: set
$cache[$id] = $data;
file_put_contents($cachefile, serialize($cache));
return true;
}
/*
* combine keys from $data array to new one.
* rename keys to be named as $value says.
*/
function filter_keys($keys, $data) {
$res = array();
foreach ($keys as $key => $value) {
// remap old key to new one
if (isset($data[$key])) {
$res[$value] = $data[$key];
continue;
}
// use already existing new name
if (isset($data[$value])) {
$res[$value] = $data[$value];
continue;
}
}
return $res;
}
/**
* Query data from Eventum server
*/
function query($id) {
global $conf;
$cache = $this->cache($id);
if ($cache !== null) {
return $cache;
}
static $client = null;
static $eventum_url, $rpc_url;
if (!$client) {
// setup RPC object
$rpc_url = $this->getConf('url') . '/rpc/xmlrpc.php';
$client = new Eventum_RPC($rpc_url);
$client->setCredentials($this->getConf('username'), $this->getConf('password'));
//$client->setDebug(1);
// Issue link
$eventum_url = $this->getConf('url') . '/view.php?id=';
}
$data['url'] = $eventum_url . $id;
try {
$data['details'] = self::filter_keys(self::$cache_keys, $client->getSimpleIssueDetails((int )$id));
} catch (Eventum_RPC_Exception $e) {
$data['error'] = $e->getMessage();
if ($conf['allowdebug']) {
$data['rpcurl'] = $rpc_url;
}
}
$data['id'] = $id;
$data['mtime'] = time();
$this->cache($id, $data);
return $data;
}
/**
* Create output
*/
function render($format, Doku_Renderer $renderer, $data) {
global $ID;
// fetch extra data from eventum
$data += $this->query($data['id']);
// link title
$link = 'issue #'. $data['id'];
if ($data['error']) {
if ($format == 'xhtml') {
$renderer->doc .= $link;
$renderer->doc .= ': '.$data['error'].'';
if (isset($data['rpcurl'])) {
$renderer->doc .= " RPC URL: {$data['rpcurl']}";
}
} else {
$renderer->cdata($data['error']);
}
return;
}
if (!isset($data['title'])) {
$data['title'] = $data['details']['summary'];
}
if ($format == 'xhtml' || $format == 'odt') {
$html = '';
$html .= $this->link($format, $data['url'], $link, $data['details']['summary']);
if ($data['title']) {
$html .= ': '. hsc($data['title']);
}
if ($data['details']['status']) {
$html .= ' '. $this->emphasis($format, '('.$data['details']['status'].')');
}
if ($data['details']['is_closed']) {
$html = $this->strike($format, $html);
}
$renderer->doc .= $this->html($format, $html);
} elseif ($format == 'odt') {
$renderer->externallink($data['url'], $link);
$renderer->cdata(': '.$data['title']);
}
return true;
}
/** odt/html export helpers, partly ripped from odt plugin */
function _xmlEntities($value) {
return str_replace( array('&','"',"'",'<','>'), array('&','"',''','<','>'), $value);
}
function strike($format, $text) {
$doc = '';
if ($format == 'xhtml') {
$doc .= '';
$doc .= $text;
$doc .= '';
} elseif ($format == 'odt') {
$doc .= '';
$doc .= $text;
$doc .= '';
}
return $doc;
}
function emphasis($format, $text) {
if ($format == 'xhtml') {
$doc .= '';
$doc .= $text;
$doc .= '';
} elseif ($format == 'odt') {
$doc .= '';
$doc .= $text;
$doc .= '';
}
return $doc;
}
function html($format, $text) {
$doc = '';
if ($format == 'xhtml') {
$doc .= $text;
} elseif ($format == 'odt') {
$doc .= '';
$doc .= $text;
$doc .= '';
}
return $doc;
}
function link($format, $url, $name, $title) {
$doc = '';
if ($format == 'xhtml') {
$doc .= ''.hsc($name).'';
} elseif ($format == 'odt') {
$url = $this->_xmlEntities($url);
$doc .= '';
$doc .= $name; // we get the name already XML encoded
$doc .= '';
}
return $doc;
}
}
//Setup VIM: ex: et ts=4 enc=utf-8 :