r49847 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r49846‎ | r49847 | r49848 >
Date:22:53, 24 April 2009
Author:demon
Status:ok (Comments)
Tags:
Comment:
Handle FIXME from r49834: split off into a class and register using ParserFirstCallInit. Also delay message loading until render(), rater than at hook-registering time.
Modified paths:
  • /trunk/extensions/RT/RT.php (modified) (history)
  • /trunk/extensions/RT/RT_body.php (added) (history)

Diff [purge]

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 @@
6161 'url' => $rt_uri,
6262 );
6363
64 -// Pull in the Internationalization file
 64+// Pull in the Internationalization file and class
6565 $wgExtensionMessagesFiles['RT'] = dirname( __FILE__ ) . '/RT.i18n.php';
 66+$wgAutoloadClasses['RT'] = dirname( __FILE__ ) . '/RT_body.php';
6667
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';
7070
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 -
48771 $rtDate = gmdate( 'YmdHis', @filemtime( __FILE__ ) );
48872 $wgCacheEpoch = max( $wgCacheEpoch, $rtDate );

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r49834* stylize.php and trailing whitespace removed...siebrand19:51, 24 April 2009

Comments

#Comment by Tim Starling (talk | contribs)   15:20, 19 May 2009

Apparently the line endings were fixed in r50079.

Status & tagging log