Index: trunk/extensions/RT/RT_body.php |
— | — | @@ -0,0 +1,415 @@ |
| 2 | +<?php
|
| 3 | +
|
| 4 | +class RT {
|
| 5 | +
|
| 6 | + /**
|
| 7 | + * Register the hook with ParserFirstCallInit
|
| 8 | + */
|
| 9 | + public static function registerHook( &$parser ) {
|
| 10 | + $parser->setHook( 'rt', array( 'RT::render' ) );
|
| 11 | + return true;
|
| 12 | + }
|
| 13 | +
|
| 14 | + // This is called to process <rt>...</rt> within a page
|
| 15 | + public static function render( $input, $args = array(), $parser = null ) {
|
| 16 | +
|
| 17 | + global $wgRequestTracker_Cachepage, $wgRequestTracker_Active, $wgRequestTracker_DBconn,
|
| 18 | + $wgRequestTracker_TIMEFORMAT_LASTUPDATED,
|
| 19 | + $wgRequestTracker_TIMEFORMAT_LASTUPDATED2,
|
| 20 | + $wgRequestTracker_TIMEFORMAT_CREATED,
|
| 21 | + $wgRequestTracker_TIMEFORMAT_CREATED2,
|
| 22 | + $wgRequestTracker_TIMEFORMAT_RESOLVED,
|
| 23 | + $wgRequestTracker_TIMEFORMAT_RESOLVED2,
|
| 24 | + $wgRequestTracker_TIMEFORMAT_NOW;
|
| 25 | +
|
| 26 | + wfLoadExtensionMessages( 'RT' );
|
| 27 | +
|
| 28 | + // Grab the number if one was given between the <tr> tags
|
| 29 | + $ticketnum = 0;
|
| 30 | + $matches = array();
|
| 31 | + if ( preg_match( '/^\s*(\d+)\s*$/', $input, $matches ) ) {
|
| 32 | + $ticketnum = $matches[0];
|
| 33 | + }
|
| 34 | +
|
| 35 | + // Disable all caching unless told not to
|
| 36 | + if ( !$wgRequestTracker_Cachepage ) {
|
| 37 | + $parser->disableCache();
|
| 38 | + }
|
| 39 | +
|
| 40 | + // Try and connect to the database if we are active
|
| 41 | + if ( $wgRequestTracker_Active ) {
|
| 42 | + global $wgUser;
|
| 43 | + $dbh = pg_connect( $wgRequestTracker_DBconn );
|
| 44 | + if ( $dbh == false ) {
|
| 45 | + wfDebug( "DB connection error\n" );
|
| 46 | + wfDebug( "Connection string: $wgRequestTracker_DBconn\n" );
|
| 47 | + $wgRequestTracker_Active = 0;
|
| 48 | + }
|
| 49 | + $tz = $wgUser->getOption( 'timecorrection' );
|
| 50 | + if ( $tz ) {
|
| 51 | + $found = array();
|
| 52 | + if ( preg_match ( '/((-?\d\d?):(\d\d))/', $tz, $found ) ) {
|
| 53 | + if ( $found[3] === '00' ) {
|
| 54 | + pg_query( "SET TIME ZONE $found[2]" );
|
| 55 | + }
|
| 56 | + else {
|
| 57 | + print( "SET TIME ZONE INTERVAL '$found[1]' HOUR TO MINUTE" );
|
| 58 | + }
|
| 59 | + }
|
| 60 | + }
|
| 61 | + }
|
| 62 | +
|
| 63 | + // If we are not 'active', we leave right away, with minimal output
|
| 64 | + if ( !$wgRequestTracker_Active ) {
|
| 65 | + if ( $ticketnum ) {
|
| 66 | + return "<span class='rt-ticket-inactive'>RT #$ticketnum</span>";
|
| 67 | + }
|
| 68 | + $msg = wfMsg( 'rt-inactive' );
|
| 69 | + return "<table class='rt-table-inactive' border='1'><tr><td>$msg</td></tr></table>";
|
| 70 | + }
|
| 71 | +
|
| 72 | + // Standard info we gather
|
| 73 | + $TZ = "AT TIME ZONE 'GMT'";
|
| 74 | + $ticketinfo = 't.id, t.subject, t.priority, INITCAP(t.status) AS status, q.name AS queue,'
|
| 75 | + . ' COALESCE(u.realname, u.name) AS owner,'
|
| 76 | + . ' u.name AS username,'
|
| 77 | + . ' COALESCE(u2.realname, u2.name) AS creator,'
|
| 78 | + . " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED'::text) AS lastupdated,"
|
| 79 | + . " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED2'::text) AS lastupdated2,"
|
| 80 | + . " TO_CHAR(now() $TZ, '$wgRequestTracker_TIMEFORMAT_NOW'::text) AS nowtime,"
|
| 81 | + . " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED'::text) AS created,"
|
| 82 | + . " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED2'::text) AS created2,"
|
| 83 | + . " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED'::text) AS resolved,"
|
| 84 | + . " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED2'::text) AS resolved2,"
|
| 85 | + . " CASE WHEN (now() $TZ - t.created) <= '1 second'::interval THEN '1 second' ELSE"
|
| 86 | + . " CASE WHEN (now() $TZ - t.created) <= '2 minute'::interval THEN EXTRACT(seconds FROM now() $TZ - t.created) || ' seconds' ELSE"
|
| 87 | + . " CASE WHEN (now() $TZ - t.created) <= '2 hour'::interval THEN EXTRACT(minutes FROM now() $TZ - t.created) || ' minutes' ELSE"
|
| 88 | + . " CASE WHEN (now() $TZ - t.created) <= '2 day'::interval THEN EXTRACT(hours FROM now() $TZ - t.created) || ' hours' ELSE"
|
| 89 | + . " EXTRACT(days FROM now() $TZ - t.created) || ' days' END END END END AS age";
|
| 90 | +
|
| 91 | + // The standard query
|
| 92 | + $ticketquery = "SELECT $ticketinfo FROM tickets t"
|
| 93 | + . ' JOIN users u ON t.owner = u.id'
|
| 94 | + . ' JOIN users u2 ON t.creator = u2.id'
|
| 95 | + . ' JOIN queues q ON t.queue = q.id';
|
| 96 | +
|
| 97 | + // If just a single number, treat it as <rt>#</rt>
|
| 98 | + if ( 1 === count( $args ) ) {
|
| 99 | + if ( preg_match( '/^\d+$/', key( $args ) ) ) {
|
| 100 | + $ticketnum = key( $args );
|
| 101 | + }
|
| 102 | + }
|
| 103 | +
|
| 104 | + // Look up a single ticket number
|
| 105 | + if ( $ticketnum ) {
|
| 106 | + $SQL = "$ticketquery AND t.id = $ticketnum";
|
| 107 | + $res = pg_query( $dbh, $SQL );
|
| 108 | + if ( !$res ) {
|
| 109 | + die ( wfMsg( 'rt-badquery' ) );
|
| 110 | + }
|
| 111 | + $info = pg_fetch_array( $res );
|
| 112 | + if ( !$info ) {
|
| 113 | + return "<span class='rt-nosuchticket'>RT #$ticketnum</span>";
|
| 114 | + }
|
| 115 | + return self::fancyLink( $info, $args, $parser, 0 );
|
| 116 | + }
|
| 117 | +
|
| 118 | + // Add in a LIMIT clause if l=xx was used
|
| 119 | + $limit = '';
|
| 120 | + if ( array_key_exists( 'l', $args ) ) {
|
| 121 | + $limit = trim( $args['l'] );
|
| 122 | + if ( !preg_match( '/^ *\d+ *$/', $limit ) ) {
|
| 123 | + die ( wfMsg ( 'rt-badlimit', $limit ) );
|
| 124 | + }
|
| 125 | + $limit = " LIMIT $limit";
|
| 126 | + }
|
| 127 | +
|
| 128 | + // Change the default ORDER BY clause if ob=xx was used
|
| 129 | + $orderby = 'ORDER BY t.lastupdated DESC, t.id';
|
| 130 | + $valid_orderby = array
|
| 131 | + (
|
| 132 | + 'id' => 't.id',
|
| 133 | + 'subject' => 't.subject',
|
| 134 | + 'priority' => 't.priority',
|
| 135 | + 'status' => 't.status',
|
| 136 | + 'queue' => 'q.name',
|
| 137 | + 'owner' => 'COALESCE(u.realname, u.name)',
|
| 138 | + 'creator' => 'COALESCE(u2.realname, u2.name)',
|
| 139 | + 'lastupdated' => 't.lastupdated',
|
| 140 | + 'created' => 't.created',
|
| 141 | + 'resolved' => 't.resolved',
|
| 142 | + );
|
| 143 | + if ( array_key_exists( 'ob', $args ) ) {
|
| 144 | + $orderby = 'ORDER BY';
|
| 145 | + $orderbyargs = trim( strtolower( $args['ob'] ) );
|
| 146 | + foreach ( preg_split( '/\s*,\s*/', $orderbyargs ) as $word ) {
|
| 147 | + $oldlen = strlen( $word );
|
| 148 | + $word = ltrim( $word, '!' );
|
| 149 | + $mod = $oldlen !== strlen( $word ) ? ' DESC' : '';
|
| 150 | + if ( !preg_match( '/^\w+$/', $word ) ) {
|
| 151 | + die ( wfMsg ( 'rt-badorderby', $word ) );
|
| 152 | + }
|
| 153 | + if ( array_key_exists( $word, $valid_orderby ) ) {
|
| 154 | + $word = $valid_orderby[$word];
|
| 155 | + }
|
| 156 | + else if ( !preg_match ( '/^\d+$/', $word ) ) {
|
| 157 | + die ( wfMsg ( 'rt-badorderby', $word ) );
|
| 158 | + }
|
| 159 | + $orderby .= " $word$mod,";
|
| 160 | + }
|
| 161 | + $orderby = rtrim( $orderby, ',' );
|
| 162 | + }
|
| 163 | +
|
| 164 | + // Determine what status to use. Default is new and open:
|
| 165 | + $searchstatus = "AND t.status IN ('new','open')";
|
| 166 | + $valid_status = array( 'new', 'open', 'resolved', 'deleted', 'stalled', 'rejected' );
|
| 167 | + if ( array_key_exists( 's', $args ) ) {
|
| 168 | + $statusargs = trim( strtolower( $args['s'] ) );
|
| 169 | + if ( $statusargs === 'all' ) {
|
| 170 | + $searchstatus = '';
|
| 171 | + }
|
| 172 | + else {
|
| 173 | + $searchstatus = 'AND t.status IN (';
|
| 174 | + foreach ( preg_split( '/\s*,\s*/', $statusargs ) as $word ) {
|
| 175 | + if ( !in_array( $word, $valid_status ) ) {
|
| 176 | + die ( wfMsg ( 'rt-badstatus', $word ) );
|
| 177 | + }
|
| 178 | + $searchstatus .= "'$word',";
|
| 179 | + }
|
| 180 | + $searchstatus = preg_replace( '/.$/', ')', $searchstatus );
|
| 181 | + }
|
| 182 | + }
|
| 183 | +
|
| 184 | + // See if we are limiting to one or more queues
|
| 185 | + $searchq = '';
|
| 186 | + if ( array_key_exists( 'q', $args ) ) {
|
| 187 | + $qargs = trim( strtolower( $args['q'] ) );
|
| 188 | + $searchq = 'AND LOWER(q.name) IN (';
|
| 189 | + foreach ( preg_split( '/\s*,\s*/', $qargs ) as $word ) {
|
| 190 | + $word = trim( $word );
|
| 191 | + if ( !preg_match( '/^[\w \.-]+$/', $word ) ) {
|
| 192 | + die ( wfMsg ( 'rt-badqueue', $word ) );
|
| 193 | + }
|
| 194 | + $searchq .= "'$word',";
|
| 195 | + }
|
| 196 | + $searchq = preg_replace( '/.$/', ')', $searchq );
|
| 197 | + }
|
| 198 | +
|
| 199 | + // See if we are limiting to one or more owners
|
| 200 | + $searchowner = '';
|
| 201 | + if ( array_key_exists( 'o', $args ) ) {
|
| 202 | + $oargs = trim( strtolower( $args['o'] ) );
|
| 203 | + $searchowner = 'AND LOWER(u.name) IN (';
|
| 204 | + foreach ( preg_split( '/\s*,\s*/', $oargs ) as $word ) {
|
| 205 | + $word = trim( $word );
|
| 206 | + if ( !preg_match( '/^[\w\@\.\-\:\/]+$/', $word ) ) {
|
| 207 | + die ( wfMsg ( 'rt-badowner', $word ) );
|
| 208 | + }
|
| 209 | + $searchowner .= "'$word',";
|
| 210 | + }
|
| 211 | + $searchowner = preg_replace( '/.$/', ')', $searchowner );
|
| 212 | + }
|
| 213 | +
|
| 214 | + // Build and run the final query
|
| 215 | + $SQL = "$ticketquery $searchq $searchowner $searchstatus $orderby $limit";
|
| 216 | + $res = pg_query( $dbh, $SQL );
|
| 217 | + if ( !$res ) {
|
| 218 | + die ( wfMsg( 'rt-badquery' ) );
|
| 219 | + }
|
| 220 | + $info = pg_fetch_all( $res );
|
| 221 | + if ( !$info ) {
|
| 222 | + $msg = wfMsg( 'rt-nomatches' );
|
| 223 | + return "<table class='rt-table-empty' border='1'><tr><th>$msg</th><tr></table>";
|
| 224 | + }
|
| 225 | +
|
| 226 | + // Figure out what columns to show
|
| 227 | + // Anything specifically requested is shown
|
| 228 | + // Everything else is either on or off by default, but can be overidden
|
| 229 | + $output = '';
|
| 230 | +
|
| 231 | + // The queue: show by default unless searching a single queue
|
| 232 | + $showqueue = 1;
|
| 233 | + if ( array_key_exists( 'noqueue', $args )
|
| 234 | + || ( $searchq
|
| 235 | + && false === strpos( $searchq, ',' )
|
| 236 | + && !array_key_exists( 'queue', $args ) ) ) {
|
| 237 | + $showqueue = 0;
|
| 238 | + }
|
| 239 | +
|
| 240 | + // The owner: show by default unless searching a single owner
|
| 241 | + $showowner = 1;
|
| 242 | + if ( array_key_exists( 'noowner', $args )
|
| 243 | + || ( $searchowner
|
| 244 | + && false === strpos( $searchowner, ',' )
|
| 245 | + && !array_key_exists( 'owner', $args ) ) ) {
|
| 246 | + $showowner = 0;
|
| 247 | + }
|
| 248 | +
|
| 249 | + // The status: show by default unless searching a single status
|
| 250 | + $showstatus = 1;
|
| 251 | + if ( array_key_exists( 'nostatus', $args )
|
| 252 | + || ( false === strpos( $searchstatus, ',' )
|
| 253 | + && !array_key_exists( 'status', $args ) ) ) {
|
| 254 | + $showstatus = 0;
|
| 255 | + }
|
| 256 | +
|
| 257 | + // Things we always show unless told not to:
|
| 258 | + $showsubject = ! array_key_exists( 'nosubject', $args );
|
| 259 | + $showupdated = ! array_key_exists( 'noupdated', $args );
|
| 260 | + $showticket = ! array_key_exists( 'noticket', $args );
|
| 261 | +
|
| 262 | + // Things we don't show unless asked to:
|
| 263 | + $showpriority = array_key_exists( 'priority', $args );
|
| 264 | + $showupdated2 = array_key_exists( 'updated2', $args );
|
| 265 | + $showcreated = array_key_exists( 'created', $args );
|
| 266 | + $showcreated2 = array_key_exists( 'created2', $args );
|
| 267 | + $showresolved = array_key_exists( 'resolved', $args );
|
| 268 | + $showresolved2 = array_key_exists( 'resolved2', $args );
|
| 269 | + $showage = array_key_exists( 'age', $args );
|
| 270 | +
|
| 271 | + // Unless 'tablerows' has been set, output the table and header tags
|
| 272 | + if ( !array_key_exists( 'tablerows', $args ) ) {
|
| 273 | +
|
| 274 | + $output = "<table class='rt-table' border='1'><tr>";
|
| 275 | +
|
| 276 | + if ( $showticket ) { $output .= '<th>Ticket</th>'; }
|
| 277 | + if ( $showqueue ) { $output .= '<th>Queue</th>'; }
|
| 278 | + if ( $showsubject ) { $output .= '<th>Subject</th>'; }
|
| 279 | + if ( $showstatus ) { $output .= '<th>Status</th>'; }
|
| 280 | + if ( $showpriority ) { $output .= '<th>Priority</th>'; }
|
| 281 | + if ( $showowner ) { $output .= '<th>Owner</th>'; }
|
| 282 | + if ( $showupdated ) { $output .= '<th>Last updated</th>'; }
|
| 283 | + if ( $showupdated2 ) { $output .= '<th>Last updated</th>'; }
|
| 284 | + if ( $showcreated ) { $output .= '<th>Created</th>'; }
|
| 285 | + if ( $showcreated2 ) { $output .= '<th>Created</th>'; }
|
| 286 | + if ( $showresolved ) { $output .= '<th>Resolved</th>'; }
|
| 287 | + if ( $showresolved2 ) { $output .= '<th>Resolved</th>'; }
|
| 288 | + if ( $showage ) { $output .= '<th>Age</th>'; }
|
| 289 | +
|
| 290 | + $output .= '</tr>';
|
| 291 | + }
|
| 292 | +
|
| 293 | + foreach ( $info as $row ) {
|
| 294 | +
|
| 295 | + if ( $showticket ) {
|
| 296 | + $id = self::fancyLink( $row, $args, $parser, 1 );
|
| 297 | + $output .= "<td style='white-space: nowrap'>$id</td>";
|
| 298 | + }
|
| 299 | + if ( $showqueue ) { $output .= '<td>' . htmlspecialchars( $row['queue'] ) . '</td>'; }
|
| 300 | + if ( $showsubject ) { $output .= '<td>' . htmlspecialchars( $row['subject'] ) . '</td>'; }
|
| 301 | + if ( $showstatus ) { $output .= '<td>' . htmlspecialchars( $row['status'] ) . '</td>'; }
|
| 302 | + if ( $showpriority ) { $output .= '<td>' . htmlspecialchars( $row['priority'] ) . '</td>'; }
|
| 303 | + if ( $showowner ) { $output .= '<td>' . htmlspecialchars( $row['owner'] ) . '</td>'; }
|
| 304 | + if ( $showupdated ) { $output .= '<td>' . $row['lastupdated'] . '</td>'; }
|
| 305 | + if ( $showupdated2 ) { $output .= '<td>' . $row['lastupdated2'] . '</td>'; }
|
| 306 | + if ( $showcreated ) { $output .= '<td>' . $row['created'] . '</td>'; }
|
| 307 | + if ( $showcreated2 ) { $output .= '<td>' . $row['created2'] . '</td>'; }
|
| 308 | + if ( $showresolved ) { $output .= '<td>' . $row['resolved'] . '</td>'; }
|
| 309 | + if ( $showresolved2 ) { $output .= '<td>' . $row['resolved2'] . '</td>'; }
|
| 310 | + if ( $showage ) { $output .= '<td>' . $row['age'] . '</td>'; }
|
| 311 | + $output .= '<tr>';
|
| 312 | + }
|
| 313 | +
|
| 314 | + if ( !array_key_exists( 'tablerows', $args ) ) {
|
| 315 | + $output .= '</table>';
|
| 316 | + }
|
| 317 | +
|
| 318 | + return $output;
|
| 319 | + }
|
| 320 | +
|
| 321 | + private static function fancyLink( $row, $args, $parser, $istable ) {
|
| 322 | +
|
| 323 | + global $wgRequestTracker_URL, $wgRequestTracker_Formats, $wgRequestTracker_Useballoons;
|
| 324 | +
|
| 325 | + $ticketnum = $row['id'];
|
| 326 | + $ret = "[$wgRequestTracker_URL=$ticketnum RT #$ticketnum]";
|
| 327 | +
|
| 328 | + # Check for any custom format args in the rt tag.
|
| 329 | + # If any are found, use that and ignore any other args
|
| 330 | + $foundformat = 0;
|
| 331 | + foreach ( array_keys( $args ) as $val ) {
|
| 332 | + if ( array_key_exists( $val, $wgRequestTracker_Formats ) ) {
|
| 333 | + $format = $wgRequestTracker_Formats[$val];
|
| 334 | + foreach ( array_keys( $row ) as $rev ) {
|
| 335 | + $format = str_replace( "?$rev?", "$row[$rev]", $format );
|
| 336 | + }
|
| 337 | + $ret .= " $format";
|
| 338 | + $foundformat = 1;
|
| 339 | + break;
|
| 340 | + }
|
| 341 | + }
|
| 342 | +
|
| 343 | + # Process any column-based args to the rt tag
|
| 344 | + if ( !$foundformat and !$istable ) {
|
| 345 | + foreach ( array_keys( $args ) as $val ) {
|
| 346 | + if ( array_key_exists( $val, $row ) ) {
|
| 347 | + $format = $args[$val];
|
| 348 | + if ( false === strpos( $format, '?' ) ) {
|
| 349 | + $showname = $val === 'lastupdated' ? 'Last updated' : ucfirst( $val );
|
| 350 | + $ret .= " $showname: $row[$val]";
|
| 351 | + }
|
| 352 | + else {
|
| 353 | + $ret .= " " . str_replace( '?', $row[$val], $format );
|
| 354 | + }
|
| 355 | + }
|
| 356 | + }
|
| 357 | + }
|
| 358 | +
|
| 359 | + $ret = $parser->recursiveTagParse( $ret );
|
| 360 | +
|
| 361 | + // Not using balloons? Just return the current text
|
| 362 | + if ( !$wgRequestTracker_Useballoons || array_key_exists( 'noballoon', $args ) ) {
|
| 363 | + return "<span class='rt-ticket-noballoon'>$ret</span>";
|
| 364 | + }
|
| 365 | +
|
| 366 | + $safesub = preg_replace( '/\"/', '\"', $row['subject'] );
|
| 367 | + $safesub = preg_replace( '/\'/', "\'", $safesub );
|
| 368 | + $safesub = htmlspecialchars( $safesub );
|
| 369 | +
|
| 370 | + $safeowner = $row['owner'];
|
| 371 | + if ( $row['owner'] !== $row['username'] ) {
|
| 372 | + $safeowner .= " ($row[username])";
|
| 373 | + }
|
| 374 | + $safeowner = preg_replace( '/\"/', '\"', $safeowner );
|
| 375 | + $safeowner = preg_replace( '/\'/', "\'", $safeowner );
|
| 376 | + $safeowner = htmlspecialchars( $safeowner );
|
| 377 | +
|
| 378 | + $safeq = preg_replace( '/\"/', '\"', $row['queue'] );
|
| 379 | + $safeq = preg_replace( '/\'/', "\'", $safeq );
|
| 380 | + $safeq = htmlspecialchars( $safeq );
|
| 381 | +
|
| 382 | + $text = "RT #<b>$ticketnum</b>";
|
| 383 | + $text .= "<br />Status: <b>$row[status]</b>";
|
| 384 | + $text .= "<br />Subject: <b>$safesub</b>";
|
| 385 | + $text .= "<br />Owner: <b>$safeowner</b>";
|
| 386 | + $text .= "<br />Queue: <b>$safeq</b>";
|
| 387 | + $text .= "<br />Created: <b>$row[created]</b>";
|
| 388 | + if ( $row['status'] === 'Resolved' ) {
|
| 389 | + $text .= "<br />Resolved: <b>$row[resolved]</b>";
|
| 390 | + }
|
| 391 | + else {
|
| 392 | + $text .= "<br />Last updated: <b>$row[lastupdated]</b>";
|
| 393 | + }
|
| 394 | +
|
| 395 | + # Prepare some balloon-tek
|
| 396 | + $link = isset( $args['link'] ) ? $args['link'] : '';
|
| 397 | + $target = isset( $args['target'] ) ? $args['target'] : '';
|
| 398 | + $sticky = isset( $args['sticky'] ) ? $args['sticky'] : '0';
|
| 399 | + $width = isset( $args['width'] ) ? $args['width'] : '0';
|
| 400 | +
|
| 401 | + $event = isset( $args['click'] ) && $args['click'] && !$link ? 'onclick' : 'onmouseover';
|
| 402 | + $event2 = '';
|
| 403 | + $event = "$event=\"balloon.showTooltip(event,'${text}',${sticky},${width})\"";
|
| 404 | +
|
| 405 | + if ( preg_match( '/onclick/', $event ) && $args['hover'] ) {
|
| 406 | + $event2 = " onmouseover=\"balloon.showTooltip(event,'" . $args['hover'] . "',0,${width})\"";
|
| 407 | + }
|
| 408 | +
|
| 409 | + $has_style = isset( $args['style'] ) && $args['style'];
|
| 410 | + $style = "style=\"" . ( $has_style ? $args['style'] . ";cursor:pointer\"" : "cursor:pointer\"" );
|
| 411 | + $target = $target ? "target=${target}" : '';
|
| 412 | + $output = "<span class='rt-ticket' ${event} ${event2} ${style}>$ret</span>";
|
| 413 | +
|
| 414 | + return $output;
|
| 415 | + }
|
| 416 | +} |
\ No newline at end of file |
Index: trunk/extensions/RT/RT.php |
— | — | @@ -60,428 +60,12 @@ |
61 | 61 | 'url' => $rt_uri, |
62 | 62 | ); |
63 | 63 | |
64 | | -// Pull in the Internationalization file |
| 64 | +// Pull in the Internationalization file and class |
65 | 65 | $wgExtensionMessagesFiles['RT'] = dirname( __FILE__ ) . '/RT.i18n.php'; |
| 66 | +$wgAutoloadClasses['RT'] = dirname( __FILE__ ) . '/RT_body.php'; |
66 | 67 | |
67 | | -// Use a hook to enable control of parsing <rt>...</rt> content |
68 | | -$wgExtensionFunctions[] = 'efRT_Setup'; |
69 | | -function efRT_Setup() { |
| 68 | +// Register hook |
| 69 | +$wgHooks['ParserFirstCallInit'][] = 'RT::registerHook'; |
70 | 70 | |
71 | | - global $wgParser, $wgUploadDirectory, $wgCommandLineMode; |
72 | | - |
73 | | - wfLoadExtensionMessages( 'RT' ); |
74 | | - |
75 | | - if ( $wgCommandLineMode ) { |
76 | | - return true; |
77 | | - } |
78 | | - |
79 | | - $wgParser->setHook( 'rt', 'rtRender' ); |
80 | | - |
81 | | - return true; |
82 | | -} |
83 | | - |
84 | | - |
85 | | -// This is called to process <rt>...</rt> within a page |
86 | | -function rtRender( $input, $args = array(), $parser = null ) { |
87 | | - |
88 | | - global $wgRequestTracker_Cachepage, $wgRequestTracker_Active, $wgRequestTracker_DBconn, |
89 | | - $wgRequestTracker_TIMEFORMAT_LASTUPDATED, |
90 | | - $wgRequestTracker_TIMEFORMAT_LASTUPDATED2, |
91 | | - $wgRequestTracker_TIMEFORMAT_CREATED, |
92 | | - $wgRequestTracker_TIMEFORMAT_CREATED2, |
93 | | - $wgRequestTracker_TIMEFORMAT_RESOLVED, |
94 | | - $wgRequestTracker_TIMEFORMAT_RESOLVED2, |
95 | | - $wgRequestTracker_TIMEFORMAT_NOW; |
96 | | - |
97 | | - // Grab the number if one was given between the <tr> tags |
98 | | - $ticketnum = 0; |
99 | | - $matches = array(); |
100 | | - if ( preg_match( '/^\s*(\d+)\s*$/', $input, $matches ) ) { |
101 | | - $ticketnum = $matches[0]; |
102 | | - } |
103 | | - |
104 | | - // Disable all caching unless told not to |
105 | | - if ( !$wgRequestTracker_Cachepage ) { |
106 | | - $parser->disableCache(); |
107 | | - } |
108 | | - |
109 | | - // Try and connect to the database if we are active |
110 | | - if ( $wgRequestTracker_Active ) { |
111 | | - global $wgUser; |
112 | | - $dbh = pg_connect( $wgRequestTracker_DBconn ); |
113 | | - if ( $dbh == false ) { |
114 | | - wfDebug( "DB connection error\n" ); |
115 | | - wfDebug( "Connection string: $wgRequestTracker_DBconn\n" ); |
116 | | - $wgRequestTracker_Active = 0; |
117 | | - } |
118 | | - $tz = $wgUser->getOption( 'timecorrection' ); |
119 | | - if ( $tz ) { |
120 | | - $found = array(); |
121 | | - if ( preg_match ( '/((-?\d\d?):(\d\d))/', $tz, $found ) ) { |
122 | | - if ( $found[3] === '00' ) { |
123 | | - pg_query( "SET TIME ZONE $found[2]" ); |
124 | | - } |
125 | | - else { |
126 | | - print( "SET TIME ZONE INTERVAL '$found[1]' HOUR TO MINUTE" ); |
127 | | - } |
128 | | - } |
129 | | - } |
130 | | - } |
131 | | - |
132 | | - // If we are not 'active', we leave right away, with minimal output |
133 | | - if ( !$wgRequestTracker_Active ) { |
134 | | - if ( $ticketnum ) { |
135 | | - return "<span class='rt-ticket-inactive'>RT #$ticketnum</span>"; |
136 | | - } |
137 | | - $msg = wfMsg( 'rt-inactive' ); |
138 | | - return "<table class='rt-table-inactive' border='1'><tr><td>$msg</td></tr></table>"; |
139 | | - } |
140 | | - |
141 | | - // Standard info we gather |
142 | | - $TZ = "AT TIME ZONE 'GMT'"; |
143 | | - $ticketinfo = 't.id, t.subject, t.priority, INITCAP(t.status) AS status, q.name AS queue,' |
144 | | - . ' COALESCE(u.realname, u.name) AS owner,' |
145 | | - . ' u.name AS username,' |
146 | | - . ' COALESCE(u2.realname, u2.name) AS creator,' |
147 | | - . " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED'::text) AS lastupdated," |
148 | | - . " TO_CHAR(t.lastupdated $TZ, '$wgRequestTracker_TIMEFORMAT_LASTUPDATED2'::text) AS lastupdated2," |
149 | | - . " TO_CHAR(now() $TZ, '$wgRequestTracker_TIMEFORMAT_NOW'::text) AS nowtime," |
150 | | - . " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED'::text) AS created," |
151 | | - . " TO_CHAR(t.created $TZ, '$wgRequestTracker_TIMEFORMAT_CREATED2'::text) AS created2," |
152 | | - . " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED'::text) AS resolved," |
153 | | - . " TO_CHAR(t.resolved $TZ, '$wgRequestTracker_TIMEFORMAT_RESOLVED2'::text) AS resolved2," |
154 | | - . " CASE WHEN (now() $TZ - t.created) <= '1 second'::interval THEN '1 second' ELSE" |
155 | | - . " CASE WHEN (now() $TZ - t.created) <= '2 minute'::interval THEN EXTRACT(seconds FROM now() $TZ - t.created) || ' seconds' ELSE" |
156 | | - . " CASE WHEN (now() $TZ - t.created) <= '2 hour'::interval THEN EXTRACT(minutes FROM now() $TZ - t.created) || ' minutes' ELSE" |
157 | | - . " CASE WHEN (now() $TZ - t.created) <= '2 day'::interval THEN EXTRACT(hours FROM now() $TZ - t.created) || ' hours' ELSE" |
158 | | - . " EXTRACT(days FROM now() $TZ - t.created) || ' days' END END END END AS age"; |
159 | | - |
160 | | - // The standard query |
161 | | - $ticketquery = "SELECT $ticketinfo FROM tickets t" |
162 | | - . ' JOIN users u ON t.owner = u.id' |
163 | | - . ' JOIN users u2 ON t.creator = u2.id' |
164 | | - . ' JOIN queues q ON t.queue = q.id'; |
165 | | - |
166 | | - // If just a single number, treat it as <rt>#</rt> |
167 | | - if ( 1 === count( $args ) ) { |
168 | | - if ( preg_match( '/^\d+$/', key( $args ) ) ) { |
169 | | - $ticketnum = key( $args ); |
170 | | - } |
171 | | - } |
172 | | - |
173 | | - // Look up a single ticket number |
174 | | - if ( $ticketnum ) { |
175 | | - $SQL = "$ticketquery AND t.id = $ticketnum"; |
176 | | - $res = pg_query( $dbh, $SQL ); |
177 | | - if ( !$res ) { |
178 | | - die ( wfMsg( 'rt-badquery' ) ); |
179 | | - } |
180 | | - $info = pg_fetch_array( $res ); |
181 | | - if ( !$info ) { |
182 | | - return "<span class='rt-nosuchticket'>RT #$ticketnum</span>"; |
183 | | - } |
184 | | - return rtFancyLink( $info, $args, $parser, 0 ); |
185 | | - } |
186 | | - |
187 | | - // Add in a LIMIT clause if l=xx was used |
188 | | - $limit = ''; |
189 | | - if ( array_key_exists( 'l', $args ) ) { |
190 | | - $limit = trim( $args['l'] ); |
191 | | - if ( !preg_match( '/^ *\d+ *$/', $limit ) ) { |
192 | | - die ( wfMsg ( 'rt-badlimit', $limit ) ); |
193 | | - } |
194 | | - $limit = " LIMIT $limit"; |
195 | | - } |
196 | | - |
197 | | - // Change the default ORDER BY clause if ob=xx was used |
198 | | - $orderby = 'ORDER BY t.lastupdated DESC, t.id'; |
199 | | - $valid_orderby = array |
200 | | - ( |
201 | | - 'id' => 't.id', |
202 | | - 'subject' => 't.subject', |
203 | | - 'priority' => 't.priority', |
204 | | - 'status' => 't.status', |
205 | | - 'queue' => 'q.name', |
206 | | - 'owner' => 'COALESCE(u.realname, u.name)', |
207 | | - 'creator' => 'COALESCE(u2.realname, u2.name)', |
208 | | - 'lastupdated' => 't.lastupdated', |
209 | | - 'created' => 't.created', |
210 | | - 'resolved' => 't.resolved', |
211 | | - ); |
212 | | - if ( array_key_exists( 'ob', $args ) ) { |
213 | | - $orderby = 'ORDER BY'; |
214 | | - $orderbyargs = trim( strtolower( $args['ob'] ) ); |
215 | | - foreach ( preg_split( '/\s*,\s*/', $orderbyargs ) as $word ) { |
216 | | - $oldlen = strlen( $word ); |
217 | | - $word = ltrim( $word, '!' ); |
218 | | - $mod = $oldlen !== strlen( $word ) ? ' DESC' : ''; |
219 | | - if ( !preg_match( '/^\w+$/', $word ) ) { |
220 | | - die ( wfMsg ( 'rt-badorderby', $word ) ); |
221 | | - } |
222 | | - if ( array_key_exists( $word, $valid_orderby ) ) { |
223 | | - $word = $valid_orderby[$word]; |
224 | | - } |
225 | | - else if ( !preg_match ( '/^\d+$/', $word ) ) { |
226 | | - die ( wfMsg ( 'rt-badorderby', $word ) ); |
227 | | - } |
228 | | - $orderby .= " $word$mod,"; |
229 | | - } |
230 | | - $orderby = rtrim( $orderby, ',' ); |
231 | | - } |
232 | | - |
233 | | - // Determine what status to use. Default is new and open: |
234 | | - $searchstatus = "AND t.status IN ('new','open')"; |
235 | | - $valid_status = array( 'new', 'open', 'resolved', 'deleted', 'stalled', 'rejected' ); |
236 | | - if ( array_key_exists( 's', $args ) ) { |
237 | | - $statusargs = trim( strtolower( $args['s'] ) ); |
238 | | - if ( $statusargs === 'all' ) { |
239 | | - $searchstatus = ''; |
240 | | - } |
241 | | - else { |
242 | | - $searchstatus = 'AND t.status IN ('; |
243 | | - foreach ( preg_split( '/\s*,\s*/', $statusargs ) as $word ) { |
244 | | - if ( !in_array( $word, $valid_status ) ) { |
245 | | - die ( wfMsg ( 'rt-badstatus', $word ) ); |
246 | | - } |
247 | | - $searchstatus .= "'$word',"; |
248 | | - } |
249 | | - $searchstatus = preg_replace( '/.$/', ')', $searchstatus ); |
250 | | - } |
251 | | - } |
252 | | - |
253 | | - // See if we are limiting to one or more queues |
254 | | - $searchq = ''; |
255 | | - if ( array_key_exists( 'q', $args ) ) { |
256 | | - $qargs = trim( strtolower( $args['q'] ) ); |
257 | | - $searchq = 'AND LOWER(q.name) IN ('; |
258 | | - foreach ( preg_split( '/\s*,\s*/', $qargs ) as $word ) { |
259 | | - $word = trim( $word ); |
260 | | - if ( !preg_match( '/^[\w \.-]+$/', $word ) ) { |
261 | | - die ( wfMsg ( 'rt-badqueue', $word ) ); |
262 | | - } |
263 | | - $searchq .= "'$word',"; |
264 | | - } |
265 | | - $searchq = preg_replace( '/.$/', ')', $searchq ); |
266 | | - } |
267 | | - |
268 | | - // See if we are limiting to one or more owners |
269 | | - $searchowner = ''; |
270 | | - if ( array_key_exists( 'o', $args ) ) { |
271 | | - $oargs = trim( strtolower( $args['o'] ) ); |
272 | | - $searchowner = 'AND LOWER(u.name) IN ('; |
273 | | - foreach ( preg_split( '/\s*,\s*/', $oargs ) as $word ) { |
274 | | - $word = trim( $word ); |
275 | | - if ( !preg_match( '/^[\w\@\.\-\:\/]+$/', $word ) ) { |
276 | | - die ( wfMsg ( 'rt-badowner', $word ) ); |
277 | | - } |
278 | | - $searchowner .= "'$word',"; |
279 | | - } |
280 | | - $searchowner = preg_replace( '/.$/', ')', $searchowner ); |
281 | | - } |
282 | | - |
283 | | - // Build and run the final query |
284 | | - $SQL = "$ticketquery $searchq $searchowner $searchstatus $orderby $limit"; |
285 | | - $res = pg_query( $dbh, $SQL ); |
286 | | - if ( !$res ) { |
287 | | - die ( wfMsg( 'rt-badquery' ) ); |
288 | | - } |
289 | | - $info = pg_fetch_all( $res ); |
290 | | - if ( !$info ) { |
291 | | - $msg = wfMsg( 'rt-nomatches' ); |
292 | | - return "<table class='rt-table-empty' border='1'><tr><th>$msg</th><tr></table>"; |
293 | | - } |
294 | | - |
295 | | - // Figure out what columns to show |
296 | | - // Anything specifically requested is shown |
297 | | - // Everything else is either on or off by default, but can be overidden |
298 | | - $output = ''; |
299 | | - |
300 | | - // The queue: show by default unless searching a single queue |
301 | | - $showqueue = 1; |
302 | | - if ( array_key_exists( 'noqueue', $args ) |
303 | | - || ( $searchq |
304 | | - && false === strpos( $searchq, ',' ) |
305 | | - && !array_key_exists( 'queue', $args ) ) ) { |
306 | | - $showqueue = 0; |
307 | | - } |
308 | | - |
309 | | - // The owner: show by default unless searching a single owner |
310 | | - $showowner = 1; |
311 | | - if ( array_key_exists( 'noowner', $args ) |
312 | | - || ( $searchowner |
313 | | - && false === strpos( $searchowner, ',' ) |
314 | | - && !array_key_exists( 'owner', $args ) ) ) { |
315 | | - $showowner = 0; |
316 | | - } |
317 | | - |
318 | | - // The status: show by default unless searching a single status |
319 | | - $showstatus = 1; |
320 | | - if ( array_key_exists( 'nostatus', $args ) |
321 | | - || ( false === strpos( $searchstatus, ',' ) |
322 | | - && !array_key_exists( 'status', $args ) ) ) { |
323 | | - $showstatus = 0; |
324 | | - } |
325 | | - |
326 | | - // Things we always show unless told not to: |
327 | | - $showsubject = ! array_key_exists( 'nosubject', $args ); |
328 | | - $showupdated = ! array_key_exists( 'noupdated', $args ); |
329 | | - $showticket = ! array_key_exists( 'noticket', $args ); |
330 | | - |
331 | | - // Things we don't show unless asked to: |
332 | | - $showpriority = array_key_exists( 'priority', $args ); |
333 | | - $showupdated2 = array_key_exists( 'updated2', $args ); |
334 | | - $showcreated = array_key_exists( 'created', $args ); |
335 | | - $showcreated2 = array_key_exists( 'created2', $args ); |
336 | | - $showresolved = array_key_exists( 'resolved', $args ); |
337 | | - $showresolved2 = array_key_exists( 'resolved2', $args ); |
338 | | - $showage = array_key_exists( 'age', $args ); |
339 | | - |
340 | | - // Unless 'tablerows' has been set, output the table and header tags |
341 | | - if ( !array_key_exists( 'tablerows', $args ) ) { |
342 | | - |
343 | | - $output = "<table class='rt-table' border='1'><tr>"; |
344 | | - |
345 | | - if ( $showticket ) { $output .= '<th>Ticket</th>'; } |
346 | | - if ( $showqueue ) { $output .= '<th>Queue</th>'; } |
347 | | - if ( $showsubject ) { $output .= '<th>Subject</th>'; } |
348 | | - if ( $showstatus ) { $output .= '<th>Status</th>'; } |
349 | | - if ( $showpriority ) { $output .= '<th>Priority</th>'; } |
350 | | - if ( $showowner ) { $output .= '<th>Owner</th>'; } |
351 | | - if ( $showupdated ) { $output .= '<th>Last updated</th>'; } |
352 | | - if ( $showupdated2 ) { $output .= '<th>Last updated</th>'; } |
353 | | - if ( $showcreated ) { $output .= '<th>Created</th>'; } |
354 | | - if ( $showcreated2 ) { $output .= '<th>Created</th>'; } |
355 | | - if ( $showresolved ) { $output .= '<th>Resolved</th>'; } |
356 | | - if ( $showresolved2 ) { $output .= '<th>Resolved</th>'; } |
357 | | - if ( $showage ) { $output .= '<th>Age</th>'; } |
358 | | - |
359 | | - $output .= '</tr>'; |
360 | | - } |
361 | | - |
362 | | - foreach ( $info as $row ) { |
363 | | - |
364 | | - if ( $showticket ) { |
365 | | - $id = rtFancyLink( $row, $args, $parser, 1 ); |
366 | | - $output .= "<td style='white-space: nowrap'>$id</td>"; |
367 | | - } |
368 | | - if ( $showqueue ) { $output .= '<td>' . htmlspecialchars( $row['queue'] ) . '</td>'; } |
369 | | - if ( $showsubject ) { $output .= '<td>' . htmlspecialchars( $row['subject'] ) . '</td>'; } |
370 | | - if ( $showstatus ) { $output .= '<td>' . htmlspecialchars( $row['status'] ) . '</td>'; } |
371 | | - if ( $showpriority ) { $output .= '<td>' . htmlspecialchars( $row['priority'] ) . '</td>'; } |
372 | | - if ( $showowner ) { $output .= '<td>' . htmlspecialchars( $row['owner'] ) . '</td>'; } |
373 | | - if ( $showupdated ) { $output .= '<td>' . $row['lastupdated'] . '</td>'; } |
374 | | - if ( $showupdated2 ) { $output .= '<td>' . $row['lastupdated2'] . '</td>'; } |
375 | | - if ( $showcreated ) { $output .= '<td>' . $row['created'] . '</td>'; } |
376 | | - if ( $showcreated2 ) { $output .= '<td>' . $row['created2'] . '</td>'; } |
377 | | - if ( $showresolved ) { $output .= '<td>' . $row['resolved'] . '</td>'; } |
378 | | - if ( $showresolved2 ) { $output .= '<td>' . $row['resolved2'] . '</td>'; } |
379 | | - if ( $showage ) { $output .= '<td>' . $row['age'] . '</td>'; } |
380 | | - $output .= '<tr>'; |
381 | | - } |
382 | | - |
383 | | - if ( !array_key_exists( 'tablerows', $args ) ) { |
384 | | - $output .= '</table>'; |
385 | | - } |
386 | | - |
387 | | - return $output; |
388 | | -} |
389 | | - |
390 | | - |
391 | | -function rtFancyLink( $row, $args, $parser, $istable ) { |
392 | | - |
393 | | - global $wgRequestTracker_URL, $wgRequestTracker_Formats, $wgRequestTracker_Useballoons; |
394 | | - |
395 | | - $ticketnum = $row['id']; |
396 | | - $ret = "[$wgRequestTracker_URL=$ticketnum RT #$ticketnum]"; |
397 | | - |
398 | | - # Check for any custom format args in the rt tag. |
399 | | - # If any are found, use that and ignore any other args |
400 | | - $foundformat = 0; |
401 | | - foreach ( array_keys( $args ) as $val ) { |
402 | | - if ( array_key_exists( $val, $wgRequestTracker_Formats ) ) { |
403 | | - $format = $wgRequestTracker_Formats[$val]; |
404 | | - foreach ( array_keys( $row ) as $rev ) { |
405 | | - $format = str_replace( "?$rev?", "$row[$rev]", $format ); |
406 | | - } |
407 | | - $ret .= " $format"; |
408 | | - $foundformat = 1; |
409 | | - break; |
410 | | - } |
411 | | - } |
412 | | - |
413 | | - # Process any column-based args to the rt tag |
414 | | - if ( !$foundformat and !$istable ) { |
415 | | - foreach ( array_keys( $args ) as $val ) { |
416 | | - if ( array_key_exists( $val, $row ) ) { |
417 | | - $format = $args[$val]; |
418 | | - if ( false === strpos( $format, '?' ) ) { |
419 | | - $showname = $val === 'lastupdated' ? 'Last updated' : ucfirst( $val ); |
420 | | - $ret .= " $showname: $row[$val]"; |
421 | | - } |
422 | | - else { |
423 | | - $ret .= " " . str_replace( '?', $row[$val], $format ); |
424 | | - } |
425 | | - } |
426 | | - } |
427 | | - } |
428 | | - |
429 | | - $ret = $parser->recursiveTagParse( $ret ); |
430 | | - |
431 | | - // Not using balloons? Just return the current text |
432 | | - if ( !$wgRequestTracker_Useballoons || array_key_exists( 'noballoon', $args ) ) { |
433 | | - return "<span class='rt-ticket-noballoon'>$ret</span>"; |
434 | | - } |
435 | | - |
436 | | - $safesub = preg_replace( '/\"/', '\"', $row['subject'] ); |
437 | | - $safesub = preg_replace( '/\'/', "\'", $safesub ); |
438 | | - $safesub = htmlspecialchars( $safesub ); |
439 | | - |
440 | | - $safeowner = $row['owner']; |
441 | | - if ( $row['owner'] !== $row['username'] ) { |
442 | | - $safeowner .= " ($row[username])"; |
443 | | - } |
444 | | - $safeowner = preg_replace( '/\"/', '\"', $safeowner ); |
445 | | - $safeowner = preg_replace( '/\'/', "\'", $safeowner ); |
446 | | - $safeowner = htmlspecialchars( $safeowner ); |
447 | | - |
448 | | - $safeq = preg_replace( '/\"/', '\"', $row['queue'] ); |
449 | | - $safeq = preg_replace( '/\'/', "\'", $safeq ); |
450 | | - $safeq = htmlspecialchars( $safeq ); |
451 | | - |
452 | | - $text = "RT #<b>$ticketnum</b>"; |
453 | | - $text .= "<br />Status: <b>$row[status]</b>"; |
454 | | - $text .= "<br />Subject: <b>$safesub</b>"; |
455 | | - $text .= "<br />Owner: <b>$safeowner</b>"; |
456 | | - $text .= "<br />Queue: <b>$safeq</b>"; |
457 | | - $text .= "<br />Created: <b>$row[created]</b>"; |
458 | | - if ( $row['status'] === 'Resolved' ) { |
459 | | - $text .= "<br />Resolved: <b>$row[resolved]</b>"; |
460 | | - } |
461 | | - else { |
462 | | - $text .= "<br />Last updated: <b>$row[lastupdated]</b>"; |
463 | | - } |
464 | | - |
465 | | - # Prepare some balloon-tek |
466 | | - $link = isset( $args['link'] ) ? $args['link'] : ''; |
467 | | - $target = isset( $args['target'] ) ? $args['target'] : ''; |
468 | | - $sticky = isset( $args['sticky'] ) ? $args['sticky'] : '0'; |
469 | | - $width = isset( $args['width'] ) ? $args['width'] : '0'; |
470 | | - |
471 | | - $event = isset( $args['click'] ) && $args['click'] && !$link ? 'onclick' : 'onmouseover'; |
472 | | - $event2 = ''; |
473 | | - $event = "$event=\"balloon.showTooltip(event,'${text}',${sticky},${width})\""; |
474 | | - |
475 | | - if ( preg_match( '/onclick/', $event ) && $args['hover'] ) { |
476 | | - $event2 = " onmouseover=\"balloon.showTooltip(event,'" . $args['hover'] . "',0,${width})\""; |
477 | | - } |
478 | | - |
479 | | - $has_style = isset( $args['style'] ) && $args['style']; |
480 | | - $style = "style=\"" . ( $has_style ? $args['style'] . ";cursor:pointer\"" : "cursor:pointer\"" ); |
481 | | - $target = $target ? "target=${target}" : ''; |
482 | | - $output = "<span class='rt-ticket' ${event} ${event2} ${style}>$ret</span>"; |
483 | | - |
484 | | - return $output; |
485 | | -} |
486 | | - |
487 | 71 | $rtDate = gmdate( 'YmdHis', @filemtime( __FILE__ ) ); |
488 | 72 | $wgCacheEpoch = max( $wgCacheEpoch, $rtDate ); |