Extension talk:RT
Add topicHey-
Looks like this only works with RT using Postgres, not with MySQL? It doesn't explicitly say so anywhere, but it appears the pg_connect is only for postgres, and hence this extension is limited to Postgres based RT installations.
quick / dirty mysql hack to RT.php
[edit]i just did this to quickly get things going for our site and will improve later.
- all my comments are marked with erikvw
- original code remains in the file, just commented out with ####
- requires a few extra parameters instead of just the $wgRequestTracker_DBconn
- $wgRequestTracker_DBhost=
- $wgRequestTracker_DBuser=
- $wgRequestTracker_DBpasswd=
- $wgRequestTracker_DBdbname=
- mostly change pg_ to mysql_, mysql does not have mysql_fetch_all, mysql can be case sensitive on table names
- use date_format() and concat() in main sql string instead.
--Erikvw 12:14, 1 June 2009 (UTC)
<?php
/**
* RT (Request Tracker) extension for MediaWiki
*
* @file
* @ingroup Extensions
*
* Usage: Add the following three lines to LocalSettings.php:
* require_once( "$IP/extensions/RT/RT.php" );
* $wgRequestTracker_URL = 'https://rt.example.com/Ticket/Display.html?id';
* $wgRequestTracker_DBconn = 'user=rt dbname=rt';
*
* For other options, please see the complete documentation
*
* @author Greg Sabino Mullane <greg@endpoint.com>
* @license MIT <http://www.opensource.org/licenses/mit-license.php>
* @version 1.8
* @link http://www.mediawiki.org/wiki/Extension:RT
*/
$rt_uri = 'http://www.mediawiki.org/wiki/Extension:RT';
## Default values: Override in LocalSettings.php, not here!
$wgRequestTracker_URL = 'http://rt.example.com/Ticket/Display.html?id';
####$wgRequestTracker_DBconn = 'user=rt dbname=rt';
$wgRequestTracker_Formats = array();
$wgRequestTracker_Cachepage = 0;
$wgRequestTracker_Useballoons = 1;
$wgRequestTracker_Active = 1;
// added erikvw - begin
$wgRequestTracker_DBuser = 'rtuser';
$wgRequestTracker_DBpasswd = 'wibble';
$wgRequestTracker_DBdbname = 'rtdb';
$wgRequestTracker_DBhost = 'rt.example.com';
####$wgRequestTracker_DBconn = array('rt.example.com','rtuser', 'wibble');
// added erikvw - end
## Time formatting
## Example formats:
## FMHH:MI AM FMMon DD, YYYY => 2:42 PM Jan 23, 2009
## HH:MI FMMonth DD, YYYY => 14:42 January 23, 2009
## YYYY/MM/DD => 2009/01/23
## For a more complete list of possibilities, please visit:
## http://www.postgresql.org/docs/current/interactive/functions-formatting.html
//removed erikvw - begin
####$wgRequestTracker_TIMEFORMAT_LASTUPDATED = 'FMHH:MI AM FMMonth DD, YYYY';
####$wgRequestTracker_TIMEFORMAT_LASTUPDATED2 = 'FMMonth DD, YYYY';
####$wgRequestTracker_TIMEFORMAT_CREATED = 'FMHH:MI AM FMMonth DD, YYYY';
####$wgRequestTracker_TIMEFORMAT_CREATED2 = 'FMMonth DD, YYYY';
####$wgRequestTracker_TIMEFORMAT_RESOLVED = 'FMHH:MI AM FMMonth DD, YYYY';
####$wgRequestTracker_TIMEFORMAT_RESOLVED2 = 'FMMonth DD, YYYY';
####$wgRequestTracker_TIMEFORMAT_NOW = 'FMHH:MI AM FMMonth DD, YYYY';
//removed erikvw - end
// added erikvw - begin
## For a more complete list of possibilities, please visit:
##http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-format
$wgRequestTracker_TIMEFORMAT_LASTUPDATED = '%h:%i %p %b %D, %Y';
$wgRequestTracker_TIMEFORMAT_LASTUPDATED2 = '%D %b %Y';
$wgRequestTracker_TIMEFORMAT_CREATED = '%h:%i %p %b %D, %Y';
$wgRequestTracker_TIMEFORMAT_CREATED2 = '%D %b %Y';
$wgRequestTracker_TIMEFORMAT_RESOLVED = '%h:%i %p %b %D, %Y';
$wgRequestTracker_TIMEFORMAT_RESOLVED2 = '%D %b %Y';
$wgRequestTracker_TIMEFORMAT_NOW = '%h:%i %p %b %D, %Y';
// added erikvw - end
// Ensure nothing is done unless run via MediaWiki
if ( !defined( 'MEDIAWIKI' ) ) {
echo( "This is an extension to the MediaWiki package and cannot be run standalone.\n" );
echo( "Please visit $rt_uri\n" );
die( -1 );
}
// Credits for Special:Version
$wgExtensionCredits['parserhook'][] = array(
'name' => 'RT',
'version' => '1.8',
'author' => array( 'Greg Sabino Mullane' ),
'description' => 'Fancy interface to RT (Request Tracker)',
'descriptionmsg' => 'rt-desc',
'url' => $rt_uri,
);
// Pull in the Internationalization file
$wgExtensionMessagesFiles['RT'] = dirname( __FILE__ ) . '/RT.i18n.php';
// Use a hook to enable control of parsing <rt>...</rt> content
$wgExtensionFunctions[] = 'efRT_Setup';
function efRT_Setup() {
global $wgParser, $wgUploadDirectory, $wgCommandLineMode;
wfLoadExtensionMessages( 'RT' );
if ( $wgCommandLineMode ) {
return true;
}
$wgParser->setHook( 'rt', 'rtRender' );
return true;
}
// This is called to process <rt>...</rt> within a page
function rtRender( $input, $args=array(), $parser=null ) {
global $wgRequestTracker_Cachepage, $wgRequestTracker_Active,
$wgRequestTracker_DBconn,
// added erikvw - begin
$wgRequestTracker_DBuser,
$wgRequestTracker_DBpasswd,
$wgRequestTracker_DBdbname,
$wgRequestTracker_DBhost,
// added erikvw - begin
$wgRequestTracker_TIMEFORMAT_LASTUPDATED,
$wgRequestTracker_TIMEFORMAT_LASTUPDATED2,
$wgRequestTracker_TIMEFORMAT_CREATED,
$wgRequestTracker_TIMEFORMAT_CREATED2,
$wgRequestTracker_TIMEFORMAT_RESOLVED,
$wgRequestTracker_TIMEFORMAT_RESOLVED2,
$wgRequestTracker_TIMEFORMAT_NOW;
// Grab the number if one was given between the <tr> tags
$ticketnum = 0;
$matches = array();
if ( preg_match( '/^\s*(\d+)\s*$/', $input, $matches ) ) {
$ticketnum = $matches[0];
}
// Disable all caching unless told not to
if ( !$wgRequestTracker_Cachepage ) {
$parser->disableCache();
}
// Try and connect to the database if we are active
if ( $wgRequestTracker_Active ) {
global $wgUser;
//added erikvw - begin
####$dbh = pg_connect( $wgRequestTracker_DBconn );
$dbh = mysql_connect( $wgRequestTracker_DBhost, $wgRequestTracker_DBuser,$wgRequestTracker_DBpasswd );
$db_selected = mysql_select_db($wgRequestTracker_DBdbname, $dbh);
//added erikvw - end
if ( $dbh == false ) {
wfDebug( "DB connection error\n" );
wfDebug( "Connection string: $wgRequestTracker_DBconn\n" );
$wgRequestTracker_Active = 0;
}
$tz = $wgUser->getOption( 'timecorrection' );
if ( $tz ) {
$found = array();
if ( preg_match ( '/((-?\d\d?):(\d\d))/', $tz, $found ) ) {
if ( $found[3] === '00' ) {
####pg_query( "SET TIME ZONE $found[2]" );
// added erikvw - begin
mysql_query( "SET TIME ZONE $found[2]" );
// added erikvw - end
}
else {
print( "SET TIME ZONE INTERVAL '$found[1]' HOUR TO MINUTE" );
}
}
}
}
// If we are not 'active', we leave right away, with minimal output
if ( !$wgRequestTracker_Active ) {
if ( $ticketnum ) {
return "<span class='rt-ticket-inactive'>RT #$ticketnum</span>";
}
$msg = wfMsg( 'rt-inactive' );
return "<table class='rt-table-inactive' border='1'><tr><td>$msg</td></tr></table>";
}
// Standard info we gather
$TZ = "AT TIME ZONE 'GMT'";
// removed erikvw - begin
/* #### $ticketinfo = 't.id, t.subject, t.priority, concat(ucase(left(t.status,1)),substring(t.status,2)) AS status, q.name AS queue,'
. ' COALESCE(u.realname, u.name) AS owner,'
. ' u.name AS username,'
. ' COALESCE(u2.realname, u2.name) AS creator,'
. " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED'::text) AS lastupdated,"
. " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED2'::text) AS lastupdated2,"
. " TO_CHAR(now() $TZ, '$wgRequestTracker_TIMEFORMAT_NOW'::text) AS nowtime,"
. " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED'::text) AS created,"
. " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED2'::text) AS created2,"
. " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED'::text) AS resolved,"
. " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED2'::text) AS resolved2,"
. " CASE WHEN (now() $TZ - t.created) <= '1 second'::interval THEN '1 second' ELSE"
. " CASE WHEN (now() $TZ - t.created) <= '2 minute'::interval THEN EXTRACT(seconds FROM now() $TZ - t.created) || ' seconds' ELSE"
. " CASE WHEN (now() $TZ - t.created) <= '2 hour'::interval THEN EXTRACT(minutes FROM now() $TZ - t.created) || ' minutes' ELSE"
. " CASE WHEN (now() $TZ - t.created) <= '2 day'::interval THEN EXTRACT(hours FROM now() $TZ - t.created) || ' hours' ELSE"
. " EXTRACT(days FROM now() $TZ - t.created) || ' days' END END END END AS age";
*/
// removed erikvw - end
// added erikvw - begin
// warning: i have REALLY simplified this, e.g. the age calc and dropped timezone issues...
$ticketinfo = 't.id, t.subject, t.priority, concat(ucase(left(t.status,1)),substring(t.status,2)) AS status, q.name AS queue,'
. ' COALESCE(u.realname, u.name) AS owner,'
. ' u.name AS username,'
. ' COALESCE(u2.realname, u2.name) AS creator,'
. " date_format(t.lastupdated, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED') AS lastupdated,"
. " date_format(t.lastupdated, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED2') AS lastupdated2,"
. " date_format(now(), '$wgRequestTracker_TIMEFORMAT_NOW') AS nowtime,"
. " date_format(t.created, '$wgRequestTracker_TIMEFORMAT_CREATED') AS created,"
. " date_format(t.created, '$wgRequestTracker_TIMEFORMAT_CREATED2') AS created2,"
. " date_format(t.resolved, '$wgRequestTracker_TIMEFORMAT_RESOLVED') AS resolved,"
. " date_format(t.resolved, '$wgRequestTracker_TIMEFORMAT_RESOLVED2') AS resolved2,"
. " datediff(now(),t.created) AS age";
// added erikvw - end
// removed erikvw - begin
// The standard query
//$ticketquery = "SELECT $ticketinfo FROM tickets t"
// . ' JOIN users u ON t.owner = u.id'
// . ' JOIN users u2 ON t.creator = u2.id'
// . ' JOIN queues q ON t.queue = q.id';
// removed erikvw - end
// added erikvw - begin
// mysql is case sensistive to the table names (rt3.6)
$ticketquery = "SELECT $ticketinfo FROM Tickets t"
. ' JOIN Users u ON t.owner = u.id'
. ' JOIN Users u2 ON t.creator = u2.id'
. ' JOIN Queues q ON t.queue = q.id';
// added erikvw - end
// If just a single number, treat it as <rt>#</rt>
if ( 1 === count( $args ) ) {
if ( preg_match( '/^\d+$/', key($args) ) ) {
$ticketnum = key($args);
}
}
// Look up a single ticket number
if ( $ticketnum ) {
$SQL = "$ticketquery AND t.id = $ticketnum";
#$res = pg_query( $dbh, $SQL );
$res = mysql_query( $SQL );
if ( !$res ) {
die ( wfMsg( 'rt-badquery' ) );
}
$info = mysql_fetch_array( $res );
if ( !$info ) {
return "<span class='rt-nosuchticket'>RT #$ticketnum</span>";
}
return rtFancyLink( $info, $args, $parser, 0 );
}
// Add in a LIMIT clause if l=xx was used
$limit = '';
if ( array_key_exists( 'l', $args ) ) {
$limit = trim( $args['l'] );
if ( !preg_match( '/^ *\d+ *$/', $limit ) ) {
die ( wfMsg ( 'rt-badlimit', $limit ) );
}
$limit = " LIMIT $limit";
}
// Change the default ORDER BY clause if ob=xx was used
$orderby = 'ORDER BY t.lastupdated DESC, t.id';
$valid_orderby = array
(
'id' => 't.id',
'subject' => 't.subject',
'priority' => 't.priority',
'status' => 't.status',
'queue' => 'q.name',
'owner' => 'COALESCE(u.realname, u.name)',
'creator' => 'COALESCE(u2.realname, u2.name)',
'lastupdated' => 't.lastupdated',
'created' => 't.created',
'resolved' => 't.resolved',
);
if ( array_key_exists( 'ob', $args ) ) {
$orderby = 'ORDER BY';
$orderbyargs = trim( strtolower( $args['ob'] ) );
foreach ( preg_split( '/\s*,\s*/', $orderbyargs ) as $word ) {
$oldlen = strlen( $word );
$word = ltrim( $word, '!' );
$mod = $oldlen !== strlen( $word ) ? ' DESC' : '';
if ( !preg_match( '/^\w+$/', $word ) ) {
die ( wfMsg ( 'rt-badorderby', $word ) );
}
if ( array_key_exists( $word, $valid_orderby ) ) {
$word = $valid_orderby[$word];
}
else if ( !preg_match ('/^\d+$/', $word ) ) {
die ( wfMsg ( 'rt-badorderby', $word ) );
}
$orderby .= " $word$mod,";
}
$orderby = rtrim( $orderby, ',' );
}
// Determine what status to use. Default is new and open:
$searchstatus = "AND t.status IN ('new','open')";
$valid_status = array( 'new', 'open', 'resolved', 'deleted', 'stalled', 'rejected' );
if ( array_key_exists( 's', $args ) ) {
$statusargs = trim( strtolower( $args['s'] ) );
if ( $statusargs === 'all' ) {
$searchstatus = '';
}
else {
$searchstatus = 'AND t.status IN (';
foreach ( preg_split( '/\s*,\s*/', $statusargs ) as $word ) {
if ( !in_array( $word, $valid_status ) ) {
die ( wfMsg ( 'rt-badstatus', $word ) );
}
$searchstatus .= "'$word',";
}
$searchstatus = preg_replace( '/.$/', ')', $searchstatus );
}
}
// See if we are limiting to one or more queues
$searchq = '';
if ( array_key_exists('q', $args ) ) {
$qargs = trim( strtolower( $args['q'] ) );
$searchq = 'AND LOWER(q.name) IN (';
foreach ( preg_split( '/\s*,\s*/', $qargs ) as $word ) {
$word = trim( $word );
if ( !preg_match( '/^[\w \.-]+$/', $word ) ) {
die ( wfMsg ( 'rt-badqueue', $word ) );
}
$searchq .= "'$word',";
}
$searchq = preg_replace( '/.$/', ')', $searchq );
}
// See if we are limiting to one or more owners
$searchowner = '';
if ( array_key_exists('o', $args ) ) {
$oargs = trim( strtolower( $args['o'] ) );
$searchowner = 'AND LOWER(u.name) IN (';
foreach ( preg_split( '/\s*,\s*/', $oargs ) as $word ) {
$word = trim( $word );
if ( !preg_match( '/^[\w\@\.\-\:\/]+$/', $word ) ) {
die ( wfMsg ( 'rt-badowner', $word ) );
}
$searchowner .= "'$word',";
}
$searchowner = preg_replace( '/.$/', ')', $searchowner );
}
// Build and run the final query
$SQL = "$ticketquery $searchq $searchowner $searchstatus $orderby $limit";
####$res = pg_query( $dbh, $SQL );
// erikvw add mysql_query - begin
$res = mysql_query( $SQL );
// erikvw add mysql_query - begin
if ( !$res ) {
die ( wfMsg( 'rt-badquery' ) );
}
####$info = pg_fetch_all( $res );
// erikvw add mysql fetch - begin
####$info = mysql_fetch_all( $res );
while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) {
$info[] = $row;
$i++;
}
// erikvw add mysql fetch - end
if ( !$info ) {
$msg = wfMsg( 'rt-nomatches' );
return "<table class='rt-table-empty' border='1'><tr><th>$msg</th><tr></table>";
}
// Figure out what columns to show
// Anything specifically requested is shown
// Everything else is either on or off by default, but can be overidden
$output = '';
// The queue: show by default unless searching a single queue
$showqueue = 1;
if ( array_key_exists('noqueue', $args )
|| ($searchq
&& false === strpos( $searchq, ',' )
&& !array_key_exists( 'queue', $args ) ) ) {
$showqueue = 0;
}
// The owner: show by default unless searching a single owner
$showowner = 1;
if ( array_key_exists( 'noowner', $args )
|| ( $searchowner
&& false === strpos( $searchowner, ',' )
&& !array_key_exists( 'owner', $args ) ) ) {
$showowner = 0;
}
// The status: show by default unless searching a single status
$showstatus = 1;
if ( array_key_exists( 'nostatus', $args )
|| ( false === strpos($searchstatus, ',' )
&& !array_key_exists( 'status', $args ) ) ) {
$showstatus = 0;
}
// Things we always show unless told not to:
$showsubject = ! array_key_exists( 'nosubject', $args );
$showupdated = ! array_key_exists( 'noupdated', $args );
$showticket = ! array_key_exists( 'noticket', $args );
// Things we don't show unless asked to:
$showpriority = array_key_exists( 'priority', $args );
$showupdated2 = array_key_exists( 'updated2', $args );
$showcreated = array_key_exists( 'created', $args );
$showcreated2 = array_key_exists( 'created2', $args );
$showresolved = array_key_exists( 'resolved', $args );
$showresolved2 = array_key_exists( 'resolved2', $args );
$showage = array_key_exists( 'age', $args );
// Unless 'tablerows' has been set, output the table and header tags
if ( !array_key_exists( 'tablerows',$args ) ) {
//changed erikvw. like wikitable and sortable #### $output = "<table class='rt-table' border='1'><tr>";
$output = "<table class='wikitable sortable' border='1'><tr>";
if ( $showticket ) { $output .= '<th>Ticket</th>'; }
if ( $showqueue ) { $output .= '<th>Queue</th>'; }
if ( $showsubject ) { $output .= '<th>Subject</th>'; }
if ( $showstatus ) { $output .= '<th>Status</th>'; }
if ( $showpriority ) { $output .= '<th>Priority</th>'; }
if ( $showowner ) { $output .= '<th>Owner</th>'; }
if ( $showupdated ) { $output .= '<th>Last updated</th>'; }
if ( $showupdated2 ) { $output .= '<th>Last updated</th>'; }
if ( $showcreated ) { $output .= '<th>Created</th>'; }
if ( $showcreated2 ) { $output .= '<th>Created</th>'; }
if ( $showresolved ) { $output .= '<th>Resolved</th>'; }
if ( $showresolved2 ) { $output .= '<th>Resolved</th>'; }
if ( $showage ) { $output .= '<th>Age</th>'; }
$output .= '</tr>';
}
foreach ( $info as $row ) {
if ( $showticket ) {
$id = rtFancyLink( $row, $args, $parser, 1 );
$output .= "<td style='white-space: nowrap'>$id</td>";
}
if ( $showqueue ) { $output .= '<td>' . htmlspecialchars( $row['queue'] ) . '</td>'; }
if ( $showsubject ) { $output .= '<td>' . htmlspecialchars( $row['subject'] ) . '</td>'; }
if ( $showstatus ) { $output .= '<td>' . htmlspecialchars( $row['status'] ) . '</td>'; }
if ( $showpriority ) { $output .= '<td>' . htmlspecialchars( $row['priority'] ). '</td>'; }
if ( $showowner ) { $output .= '<td>' . htmlspecialchars( $row['owner'] ) . '</td>'; }
if ( $showupdated ) { $output .= '<td>' . $row['lastupdated'] . '</td>'; }
if ( $showupdated2 ) { $output .= '<td>' . $row['lastupdated2'] . '</td>'; }
if ( $showcreated ) { $output .= '<td>' . $row['created'] . '</td>'; }
if ( $showcreated2 ) { $output .= '<td>' . $row['created2'] . '</td>'; }
if ( $showresolved ) { $output .= '<td>' . $row['resolved'] . '</td>'; }
if ( $showresolved2 ) { $output .= '<td>' . $row['resolved2'] . '</td>'; }
if ( $showage ) { $output .= '<td>' . $row['age'] . '</td>'; }
$output .= '<tr>';
}
if ( !array_key_exists( 'tablerows',$args ) ) {
$output .= '</table>';
}
return $output;
}
function rtFancyLink( $row, $args, $parser, $istable ) {
global $wgRequestTracker_URL, $wgRequestTracker_Formats, $wgRequestTracker_Useballoons;
$ticketnum = $row['id'];
//changed erikvw. i like it a bit simpler #### $ret = "[$wgRequestTracker_URL=$ticketnum RT #$ticketnum]";
$ret = "[$wgRequestTracker_URL=$ticketnum $ticketnum]";
## Check for any custom format args in the rt tag.
## If any are found, use that and ignore any other args
$foundformat = 0;
foreach ( array_keys( $args ) as $val ) {
if ( array_key_exists( $val, $wgRequestTracker_Formats ) ) {
$format = $wgRequestTracker_Formats[$val];
foreach ( array_keys( $row ) as $rev ) {
$format = str_replace( "?$rev?", "$row[$rev]", $format );
}
$ret .= " $format";
$foundformat = 1;
break;
}
}
## Process any column-based args to the rt tag
if ( !$foundformat and !$istable ) {
foreach ( array_keys( $args ) as $val ) {
if ( array_key_exists( $val, $row ) ) {
$format = $args[$val];
if ( false === strpos( $format, '?' ) ) {
$showname = $val === 'lastupdated' ? 'Last updated' : ucfirst( $val );
$ret .= " $showname: $row[$val]";
}
else {
$ret .= " " . str_replace( '?', $row[$val], $format );
}
}
}
}
$ret = $parser->recursiveTagParse( $ret );
// Not using balloons? Just return the current text
if ( !$wgRequestTracker_Useballoons || array_key_exists( 'noballoon', $args ) ) {
return "<span class='rt-ticket-noballoon'>$ret</span>";
}
$safesub = preg_replace( '/\"/', '\"', $row['subject'] );
$safesub = preg_replace( '/\'/', "\'", $safesub );
$safesub = htmlspecialchars( $safesub );
$safeowner = $row['owner'];
if ($row['owner'] !== $row['username']) {
$safeowner .= " ($row[username])";
}
$safeowner = preg_replace( '/\"/', '\"', $safeowner );
$safeowner = preg_replace( '/\'/', "\'", $safeowner );
$safeowner = htmlspecialchars( $safeowner );
$safeq = preg_replace( '/\"/', '\"', $row['queue'] );
$safeq = preg_replace( '/\'/', "\'", $safeq );
$safeq = htmlspecialchars( $safeq );
$text = "RT #<b>$ticketnum</b>";
$text .= "<br />Status: <b>$row[status]</b>";
$text .= "<br />Subject: <b>$safesub</b>";
$text .= "<br />Owner: <b>$safeowner</b>";
$text .= "<br />Queue: <b>$safeq</b>";
$text .= "<br />Created: <b>$row[created]</b>";
if ( $row['status'] === 'Resolved' ) {
$text .= "<br />Resolved: <b>$row[resolved]</b>";
}
else {
$text .= "<br />Last updated: <b>$row[lastupdated]</b>";
}
## Prepare some balloon-tek
$link = isset( $args['link'] ) ? $args['link'] : '';
$target = isset( $args['target'] ) ? $args['target'] : '';
$sticky = isset( $args['sticky'] ) ? $args['sticky'] : '0';
$width = isset( $args['width'] ) ? $args['width'] : '0';
$event = isset( $args['click'] ) && $args['click'] && !$link ? 'onclick' : 'onmouseover';
$event2 = '';
$event = "$event=\"balloon.showTooltip(event,'${text}',${sticky},${width})\"";
if ( preg_match( '/onclick/',$event ) && $args['hover'] ) {
$event2 = " onmouseover=\"balloon.showTooltip(event,'" . $args['hover'] . "',0,${width})\"";
}
$has_style = isset( $args['style'] ) && $args['style'];
$style = "style=\"" . ($has_style ? $args['style'] . ";cursor:pointer\"" : "cursor:pointer\"");
$target = $target ? "target=${target}" : '';
$output = "<span class='rt-ticket' ${event} ${event2} ${style}>$ret</span>";
return $output;
}
$rtDate = gmdate( 'YmdHis', @filemtime( __FILE__ ) );
$wgCacheEpoch = max( $wgCacheEpoch, $rtDate );
Hack for mysql works great thanks! --198.187.27.5 18:18, 17 June 2011 (UTC)
Callback issue with 1.17.x
[edit]I'm using PHP 5.3.2.
I ran into the following error when trying to submit a wiki entry with the rt tag: Tag hook for rt is not callable.
It turns out in RT_body.php, PHP didn't like the way the callback function was passed. Here is the relevant code:
public static function registerHook( &$parser ) {
#### $parser->setHook( 'rt', array( 'RT::render' ) );
$parser->setHook( 'rt', array( 'RT', 'render' ) );
return true;
}
I commented out the offending code. After this change everything worked as expected.
Updated for mysql on 1.23
[edit]The newer version of this extension splits RT.php into two files. The RT.php for mysql above seems not to work on Mediawiki 1.23, so here is an update:
git clone https://github.com/erikvw/RT
--Erikvw (talk) 19:08, 7 June 2014 (UTC)
- This extension seems to be unmaintained. Perhaps it is an idea to take over maintainership and apply for commit access to the WMF repo. Cheers --[[kgh]] (talk) 19:19, 7 June 2014 (UTC)
PHP 7 compatible MySQL hack
[edit]--- C:/temp/RT/mediawiki-extensions-RT-master/RT_body.php Sat Apr 06 15:27:49 2019
+++ C:/src/rt/RT_body.php Fri May 17 14:02:06 2019
@@ -15,7 +15,10 @@
global $wgRequestTracker_Cachepage,
$wgRequestTracker_Active,
- $wgRequestTracker_DBconn,
+ $wgRequestTracker_DBuser,
+ $wgRequestTracker_DBpasswd,
+ $wgRequestTracker_DBdbname,
+ $wgRequestTracker_DBhost,
$wgRequestTracker_Sortable,
$wgRequestTracker_TIMEFORMAT_LASTUPDATED,
$wgRequestTracker_TIMEFORMAT_LASTUPDATED2,
@@ -42,7 +45,7 @@
// Try and connect to the database if we are active
if ( $wgRequestTracker_Active ) {
global $wgUser;
- $dbh = pg_connect( $wgRequestTracker_DBconn );
+ $dbh = mysqli_connect( $wgRequestTracker_DBhost, $wgRequestTracker_DBuser,$wgRequestTracker_DBpasswd, $wgRequestTracker_DBdbname);
if ( $dbh == false ) {
wfDebug( "DB connection error\n" );
wfDebug( "Connection string: $wgRequestTracker_DBconn\n" );
@@ -53,7 +56,7 @@
$found = array();
if ( preg_match ( '/((-?\d\d?):(\d\d))/', $tz, $found ) ) {
if ( $found[3] === '00' ) {
- pg_query( "SET TIME ZONE $found[2]" );
+ mysqli_query( $dbh, "SET TIME ZONE $found[2]");
}
else {
print( "SET TIME ZONE INTERVAL '$found[1]' HOUR TO MINUTE" );
@@ -73,27 +76,24 @@
// Standard info we gather
$TZ = "AT TIME ZONE 'GMT'";
- $ticketinfo = 't.id, t.subject, t.priority, INITCAP(t.status) AS status, q.name AS queue,'
- . ' COALESCE(u.realname, u.name) AS owner,'
- . ' u.name AS username,'
- . ' COALESCE(u2.realname, u2.name) AS creator,'
- . " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED'::text) AS lastupdated,"
- . " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED2'::text) AS lastupdated2,"
- . " TO_CHAR(now() $TZ, '$wgRequestTracker_TIMEFORMAT_NOW'::text) AS nowtime,"
- . " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED'::text) AS created,"
- . " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED2'::text) AS created2,"
- . " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED'::text) AS resolved,"
- . " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED2'::text) AS resolved2,"
- . " ROUND(EXTRACT('epoch' FROM t.lastupdated $TZ)) AS lastupdated_epoch,"
- . " ROUND(EXTRACT('epoch' FROM t.created $TZ)) AS created_epoch,"
- . " ROUND(EXTRACT('epoch' FROM t.resolved $TZ)) AS resolved_epoch,"
- . " CASE WHEN (now() $TZ - t.created) <= '1 second'::interval THEN '1 second' ELSE"
- . " CASE WHEN (now() $TZ - t.created) <= '2 minute'::interval THEN EXTRACT(seconds FROM now() $TZ - t.created) || ' seconds' ELSE"
- . " CASE WHEN (now() $TZ - t.created) <= '2 hour'::interval THEN EXTRACT(minutes FROM now() $TZ - t.created) || ' minutes' ELSE"
- . " CASE WHEN (now() $TZ - t.created) <= '2 day'::interval THEN EXTRACT(hours FROM now() $TZ - t.created) || ' hours' ELSE"
- . " EXTRACT(days FROM now() $TZ - t.created) || ' days' END END END END AS age";
+ $ticketinfo = 't.id, t.subject, t.priority, concat(ucase(left(t.status,1)),substring(t.status,2)) AS status, q.name AS queue,'
+ . ' COALESCE(u.realname, u.name) AS owner,'
+ . ' u.name AS username,'
+ . ' COALESCE(u2.realname, u2.name) AS creator,'
+ . " date_format(t.lastupdated, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED') AS lastupdated,"
+ . " date_format(t.lastupdated, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED2') AS lastupdated2,"
+ . " date_format(now(), '$wgRequestTracker_TIMEFORMAT_NOW') AS nowtime,"
+ . " date_format(t.created, '$wgRequestTracker_TIMEFORMAT_CREATED') AS created,"
+ . " date_format(t.created, '$wgRequestTracker_TIMEFORMAT_CREATED2') AS created2,"
+ . " date_format(t.resolved, '$wgRequestTracker_TIMEFORMAT_RESOLVED') AS resolved,"
+ . " date_format(t.resolved, '$wgRequestTracker_TIMEFORMAT_RESOLVED2') AS resolved2,"
+ . " datediff(now(),t.created) AS age";
+
+ $ticketquery = "SELECT $ticketinfo FROM Tickets t"
+ . ' JOIN Users u ON t.owner = u.id'
+ . ' JOIN Users u2 ON t.creator = u2.id'
+ . ' JOIN Queues q ON t.queue = q.id';
- $ticketquery = "SELECT $ticketinfo\nFROM tickets t, queues q, users u, users u2";
$whereclause = "WHERE t.queue = q.id\nAND t.owner = u.id\nAND t.creator = u2.id";
// If just a single number, treat it as <rt>#</rt>
@@ -106,11 +106,13 @@
// Look up a single ticket number
if ( $ticketnum ) {
$SQL = "$ticketquery $whereclause\nAND t.id = $ticketnum";
- $res = pg_query( $dbh, $SQL );
+ $res = mysqli_query( $dbh, $SQL );
if ( !$res ) {
+ echo $SQL;
+ echo mysqli_error($dbh);
die ( wfMessage( 'rt-badquery' )->escaped() );
}
- $info = pg_fetch_array( $res );
+ $info = mysqli_fetch_array( $res );
if ( !$info ) {
return "<span class='rt-nosuchticket'>RT #$ticketnum</span>";
}
@@ -221,32 +223,39 @@
$whereclause .= "\nAND $searchowner";
}
- // Allow use of custom fields
- $searchcustom = '';
- if ( array_key_exists('custom', $args ) ) {
- $searchcustom = trim( $args['custom'] );
- $cfargs = trim( strtolower( $args['custom'] ) );
- $ticketquery .= ', customfields cf, objectcustomfieldvalues ov';
- $whereclause .= "\nAND ov.objectid = t.id\nAND ov.customfield=cf.id\nAND ov.disabled = 0";
- $whereclause .= "\nAND LOWER(cf.name) IN (";
- foreach ( preg_split( '/\s*,\s*/', $cfargs ) as $word ) {
- $word = trim( $word );
- if ( !preg_match( '/^[\w \.-]+$/', $word ) ) {
- die ( wfmessage ( 'rt-badcfield', $word )->escaped() );
- }
- $whereclause .= "'$word',";
- $ticketquery = preg_replace( '/COALESCE/', "\nov.content AS custom, COALESCE", $ticketquery);
- }
- $whereclause = preg_replace( '/.$/', ')', $whereclause );
- }
+ // // Allow use of custom fields
+ // $searchcustom = '';
+ // if ( array_key_exists('custom', $args ) ) {
+ // $searchcustom = trim( $args['custom'] );
+ // $cfargs = trim( strtolower( $args['custom'] ) );
+ // $ticketquery .= ', customfields cf, objectcustomfieldvalues ov';
+ // $whereclause .= "\nAND ov.objectid = t.id\nAND ov.customfield=cf.id\nAND ov.disabled = 0";
+ // $whereclause .= "\nAND LOWER(cf.name) IN (";
+ // foreach ( preg_split( '/\s*,\s*/', $cfargs ) as $word ) {
+ // $word = trim( $word );
+ // if ( !preg_match( '/^[\w \.-]+$/', $word ) ) {
+ // die ( wfmessage ( 'rt-badcfield', $word )->escaped() );
+ // }
+ // $whereclause .= "'$word',";
+ // $ticketquery = preg_replace( '/COALESCE/', "\nov.content AS custom, COALESCE", $ticketquery);
+ // }
+ // $whereclause = preg_replace( '/.$/', ')', $whereclause );
+ // }
// Build and run the final query
$SQL = "$ticketquery $whereclause $orderby $limit";
- $res = pg_query( $dbh, $SQL );
+ $res = mysqli_query( $dbh, $SQL );
if ( !$res ) {
+ echo $SQL;
+ echo mysqli_error($dbh);
die ( wfmessage( 'rt-badquery' )->escaped() );
}
- $info = pg_fetch_all( $res );
+ $info = mysqli_fetch_all( $res, MYSQLI_ASSOC );
+ // Or try stuff below if you have old PHP without mysqli_fetch_all
+ // while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
+ // $info[] = $row;
+ // $i++;
+ // }
if ( !$info ) {
$msg = wfmessage( 'rt-nomatches' )->escaped();
return "<table class='rt-table-empty' border='1'><tr><th>$msg</th><tr></table>";