X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FGlobalFunctions.php;h=0688d4a086b5cb1d3c4f809d45c6bca2eb70ed4d;hb=d42c91a23cf7c59a3cc1cc88438d087ca0d8bf6b;hp=0ae7fdcbe4243c870c017cc840f165ca5299bf47;hpb=524d56a6f160f487d61cc26153db15493f99f308;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 0ae7fdcbe4..0688d4a086 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1,22 +1,42 @@ = 3) { + $end = func_get_arg(2); + return join("",array_slice($ar[0],$start,$end)); + } else { + return join("",array_slice($ar[0],$start)); + } + } +} + +/** + * html_entity_decode exists in PHP 4.3.0+ but is FATALLY BROKEN even then, + * with no UTF-8 support. + * + * @param string $string String having html entities + * @param $quote_style + * @param string $charset Encoding set to use (default 'ISO-8859-1') + */ function do_html_entity_decode( $string, $quote_style=ENT_COMPAT, $charset='ISO-8859-1' ) { static $trans; if( !isset( $trans ) ) { @@ -61,24 +102,37 @@ function do_html_entity_decode( $string, $quote_style=ENT_COMPAT, $charset='ISO- return strtr( $string, $trans ); } + +/** + * Where as we got a random seed + * @var bool $wgTotalViews + */ $wgRandomSeeded = false; -function wfSeedRandom() -{ +/** + * Seed Mersenne Twister + * Only necessary in PHP < 4.2.0 + * + * @return bool + */ +function wfSeedRandom() { global $wgRandomSeeded; - if ( ! $wgRandomSeeded ) { + if ( ! $wgRandomSeeded && version_compare( phpversion(), '4.2.0' ) < 0 ) { $seed = hexdec(substr(md5(microtime()),-8)) & 0x7fffffff; mt_srand( $seed ); $wgRandomSeeded = true; } } -# Generates a URL from a URL-encoded title and a query string -# Title::getLocalURL() is preferred in most cases -# -function wfLocalUrl( $a, $q = '' ) -{ +/** + * Generates a URL from a URL-encoded title and a query string + * Title::getLocalURL() is preferred in most cases + * + * @param string $a URL encoded title + * @param string $q URL (default '') + */ +function wfLocalUrl( $a, $q = '' ) { global $wgServer, $wgScript, $wgArticlePath; $a = str_replace( ' ', '_', $a ); @@ -87,61 +141,37 @@ function wfLocalUrl( $a, $q = '' ) if( '' == $q ) { $a = $wgScript; } else { - $a = "{$wgScript}?{$q}"; - } + $a = $wgScript.'?'.$q; + } } else if ( '' == $q ) { - $a = str_replace( "$1", $a, $wgArticlePath ); + $a = str_replace( '$1', $a, $wgArticlePath ); } else if ($wgScript != '' ) { - $a = "{$wgScript}?title={$a}&{$q}"; + $a = "{$wgScript}?title={$a}&{$q}"; } else { //XXX hackish solution for toplevel wikis - $a = "/{$a}?{$q}"; + $a = "/{$a}?{$q}"; } return $a; } +/** + * @todo document + * @param string $a URL encoded title + * @param string $q URL (default '') + */ function wfLocalUrlE( $a, $q = '' ) { - return wfEscapeHTML( wfLocalUrl( $a, $q ) ); + return htmlspecialchars( wfLocalUrl( $a, $q ) ); # die( "Call to obsolete function wfLocalUrlE()" ); } -function wfFullUrl( $a, $q = '' ) { - wfDebugDieBacktrace( 'Call to obsolete function wfFullUrl(); use Title::getFullURL' ); -} - -function wfFullUrlE( $a, $q = '' ) { - wfDebugDieBacktrace( 'Call to obsolete function wfFullUrlE(); use Title::getFullUrlE' ); - -} - -// orphan function wfThumbUrl( $img ) -//{ -// global $wgUploadPath; -// -// $nt = Title::newFromText( $img ); -// if( !$nt ) return ""; -// -// $name = $nt->getDBkey(); -// $hash = md5( $name ); -// -// $url = "{$wgUploadPath}/thumb/" . $hash{0} . "/" . -// substr( $hash, 0, 2 ) . "/{$name}"; -// return wfUrlencode( $url ); -//} - - -function wfImageArchiveUrl( $name ) -{ - global $wgUploadPath; - - $hash = md5( substr( $name, 15) ); - $url = "{$wgUploadPath}/archive/" . $hash{0} . "/" . - substr( $hash, 0, 2 ) . "/{$name}"; - return wfUrlencode($url); -} - -function wfUrlencode ( $s ) -{ +/** + * We want / and : to be included as literal characters in our title URLs. + * %2F in the page titles seems to fatally break for some reason. + * + * @param string $s + * @return string +*/ +function wfUrlencode ( $s ) { $s = urlencode( $s ); $s = preg_replace( '/%3[Aa]/', ':', $s ); $s = preg_replace( '/%2[Ff]/', '/', $s ); @@ -149,23 +179,36 @@ function wfUrlencode ( $s ) return $s; } -function wfUtf8Sequence($codepoint) { +/** + * Return the UTF-8 sequence for a given Unicode code point. + * Currently doesn't work for values outside the Basic Multilingual Plane. + * + * @param string $codepoint UTF-8 code point. + * @return string HTML UTF-8 Entitie such as 'Ӓ'. + */ +function wfUtf8Sequence( $codepoint ) { if($codepoint < 0x80) return chr($codepoint); if($codepoint < 0x800) return chr($codepoint >> 6 & 0x3f | 0xc0) . chr($codepoint & 0x3f | 0x80); if($codepoint < 0x10000) return chr($codepoint >> 12 & 0x0f | 0xe0) . chr($codepoint >> 6 & 0x3f | 0x80) . chr($codepoint & 0x3f | 0x80); - if($codepoint < 0x100000) return chr($codepoint >> 18 & 0x07 | 0xf0) . # Double-check this + if($codepoint < 0x110000) return chr($codepoint >> 18 & 0x07 | 0xf0) . chr($codepoint >> 12 & 0x3f | 0x80) . chr($codepoint >> 6 & 0x3f | 0x80) . chr($codepoint & 0x3f | 0x80); - # Doesn't yet handle outside the BMP + + # There should be no assigned code points outside this range, but... return "&#$codepoint;"; } -# Converts numeric character entities to UTF-8 -function wfMungeToUtf8($string) { +/** + * Converts numeric character entities to UTF-8 + * + * @param string $string String to convert. + * @return string Converted string. + */ +function wfMungeToUtf8( $string ) { global $wgInputEncoding; # This is debatable #$string = iconv($wgInputEncoding, "UTF-8", $string); $string = preg_replace ( '/&#([0-9]+);/e', 'wfUtf8Sequence($1)', $string ); @@ -174,7 +217,13 @@ function wfMungeToUtf8($string) { return $string; } -# Converts a single UTF-8 character into the corresponding HTML character entity +/** + * Converts a single UTF-8 character into the corresponding HTML character + * entity (for use with preg_replace_callback) + * + * @param array $matches + * + */ function wfUtf8Entity( $matches ) { $char = $matches[0]; # Find the length @@ -188,7 +237,7 @@ function wfUtf8Entity( $matches ) { } else { $length = 1; } - + if ( $length != strlen( $char ) ) { return ''; } @@ -210,39 +259,54 @@ function wfUtf8Entity( $matches ) { return "&#$z;"; } -# Converts all multi-byte characters in a UTF-8 string into the appropriate character entity +/** + * Converts all multi-byte characters in a UTF-8 string into the appropriate + * character entity + */ function wfUtf8ToHTML($string) { return preg_replace_callback( '/[\\xc0-\\xfd][\\x80-\\xbf]*/', 'wfUtf8Entity', $string ); } -function wfDebug( $text, $logonly = false ) -{ - global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly; +/** + * @todo document + */ +function wfDebug( $text, $logonly = false ) { + global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage; + + # Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet + if ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' && !$wgDebugRawPage ) { + return; + } if ( isset( $wgOut ) && $wgDebugComments && !$logonly ) { $wgOut->debug( $text ); } - if ( "" != $wgDebugLogFile && !$wgProfileOnly ) { + if ( '' != $wgDebugLogFile && !$wgProfileOnly ) { error_log( $text, 3, $wgDebugLogFile ); } } -# Log for database errors +/** + * Log for database errors + * @param string $text Database error message. + */ function wfLogDBError( $text ) { global $wgDBerrorLog; if ( $wgDBerrorLog ) { - $text = date("D M j G:i:s T Y") . "\t$text"; + $text = date('D M j G:i:s T Y') . "\t".$text; error_log( $text, 3, $wgDBerrorLog ); } } -function logProfilingData() -{ - global $wgRequestTime, $wgDebugLogFile; +/** + * @todo document + */ +function logProfilingData() { + global $wgRequestTime, $wgDebugLogFile, $wgDebugRawPage, $wgRequest; global $wgProfiling, $wgProfileStack, $wgProfileLimit, $wgUser; $now = wfTime(); - list( $usec, $sec ) = explode( " ", $wgRequestTime ); + list( $usec, $sec ) = explode( ' ', $wgRequestTime ); $start = (float)$sec + (float)$usec; $elapsed = $now - $start; if ( $wgProfiling ) { @@ -261,25 +325,44 @@ function logProfilingData() $log = sprintf( "%s\t%04.3f\t%s\n", gmdate( 'YmdHis' ), $elapsed, urldecode( $_SERVER['REQUEST_URI'] . $forward ) ); - if ( '' != $wgDebugLogFile ) { + if ( '' != $wgDebugLogFile && ( $wgRequest->getVal('action') != 'raw' || $wgDebugRawPage ) ) { error_log( $log . $prof, 3, $wgDebugLogFile ); } } } - -function wfReadOnly() -{ +/** + * Check if the wiki read-only lock file is present. This can be used to lock + * off editing functions, but doesn't guarantee that the database will not be + * modified. + * @return bool + */ +function wfReadOnly() { global $wgReadOnlyFile; - if ( "" == $wgReadOnlyFile ) { return false; } + if ( '' == $wgReadOnlyFile ) { + return false; + } return is_file( $wgReadOnlyFile ); } -$wgReplacementKeys = array( "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9" ); +/** + * Keys strings for replacement + * @global array $wgReplacementKeys + */ +$wgReplacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' ); -# Get a message from anywhere +/** + * Get a message from anywhere + */ function wfMsg( $key ) { + global $wgRequest; + if ( $wgRequest->getVal( 'debugmsg' ) ) { + if ( $key == 'linktrail' /* a special case where we want to return something specific */ ) + return "/^()(.*)$/sD"; + else + return $key; + } $args = func_get_args(); if ( count( $args ) ) { array_shift( $args ); @@ -287,7 +370,27 @@ function wfMsg( $key ) { return wfMsgReal( $key, $args, true ); } -# Get a message from the language file +/** + * Get a message from anywhere, but don't call Language::convert + */ +function wfMsgNoConvert( $key ) { + global $wgRequest; + if ( $wgRequest->getVal( 'debugmsg' ) ) { + if ( $key == 'linktrail' /* a special case where we want to return something specific */ ) + return "/^()(.*)$/sD"; + else + return $key; + } + $args = func_get_args(); + if ( count( $args ) ) { + array_shift( $args ); + } + return wfMsgReal( $key, $args, true, false ); +} + +/** + * Get a message from the language file + */ function wfMsgNoDB( $key ) { $args = func_get_args(); if ( count( $args ) ) { @@ -296,8 +399,21 @@ function wfMsgNoDB( $key ) { return wfMsgReal( $key, $args, false ); } -# Really get a message -function wfMsgReal( $key, $args, $useDB ) { +/** + * Get a message from the language file, but don't call Language::convert + */ +function wfMsgNoDBNoConvert( $key ) { + $args = func_get_args(); + if ( count( $args ) ) { + array_shift( $args ); + } + return wfMsgReal( $key, $args, false, false ); +} + +/** + * Really get a message + */ +function wfMsgReal( $key, $args, $useDB, $convert=true ) { global $wgReplacementKeys, $wgMessageCache, $wgLang; $fname = 'wfMsg'; @@ -311,6 +427,10 @@ function wfMsgReal( $key, $args, $useDB ) { $message = "<$key>"; } + if ( $convert ) { + $message = $wgLang->convert($message); + } + # Replace arguments if( count( $args ) ) { $message = str_replace( $wgReplacementKeys, $args, $message ); @@ -319,46 +439,14 @@ function wfMsgReal( $key, $args, $useDB ) { return $message; } -function wfCleanFormFields( $fields ) -{ - wfDebugDieBacktrace( 'Call to obsolete wfCleanFormFields(). Use wgRequest instead...' ); -} - -function wfMungeQuotes( $in ) -{ - $out = str_replace( '%', '%25', $in ); - $out = str_replace( "'", '%27', $out ); - $out = str_replace( '"', '%22', $out ); - return $out; -} - -function wfDemungeQuotes( $in ) -{ - $out = str_replace( '%22', '"', $in ); - $out = str_replace( '%27', "'", $out ); - $out = str_replace( '%25', '%', $out ); - return $out; -} - -function wfCleanQueryVar( $var ) -{ - wfDebugDieBacktrace( 'Call to obsolete function wfCleanQueryVar(); use wgRequest instead' ); -} - -function wfSearch( $s ) -{ - $se = new SearchEngine( $s ); - $se->showResults(); -} -function wfGo( $s ) -{ # pick the nearest match - $se = new SearchEngine( $s ); - $se->goResult(); -} -# Just like exit() but makes a note of it. -function wfAbruptExit(){ +/** + * Just like exit() but makes a note of it. + * Commits open transactions except if the error parameter is set + */ +function wfAbruptExit( $error = false ){ + global $wgLoadBalancer; static $called = false; if ( $called ){ exit(); @@ -372,12 +460,29 @@ function wfAbruptExit(){ $line = $bt[$i]['line']; wfDebug("WARNING: Abrupt exit in $file at line $line\n"); } - } else { + } else { wfDebug('WARNING: Abrupt exit\n'); } + if ( !$error ) { + $wgLoadBalancer->closeAll(); + } exit(); } +/** + * @todo document + */ +function wfErrorExit() { + wfAbruptExit( true ); +} + +/** + * Die with a backtrace + * This is meant as a debugging aid to track down where bad data comes from. + * Shouldn't be used in production code except maybe in "shouldn't happen" areas. + * + * @param string $msg Message shown when dieing. + */ function wfDebugDieBacktrace( $msg = '' ) { global $wgCommandLineMode; @@ -392,13 +497,13 @@ function wfDebugDieBacktrace( $msg = '' ) { $f = explode( DIRECTORY_SEPARATOR, $call['file'] ); $file = $f[count($f)-1]; if ( $wgCommandLineMode ) { - $msg .= "$file line {$call['line']}, in "; + $msg .= "$file line {$call['line']} calls "; } else { - $msg .= '
  • ' . $file . " line " . $call['line'] . ', in '; + $msg .= '
  • ' . $file . ' line ' . $call['line'] . ' calls '; } if( !empty( $call['class'] ) ) $msg .= $call['class'] . '::'; - $msg .= $call['function'] . "()"; - + $msg .= $call['function'] . '()'; + if ( $wgCommandLineMode ) { $msg .= "\n"; } else { @@ -409,206 +514,30 @@ function wfDebugDieBacktrace( $msg = '' ) { die( $msg ); } -function wfNumberOfArticles() -{ - global $wgNumberOfArticles; - - wfLoadSiteStats(); - return $wgNumberOfArticles; -} - -/* private */ function wfLoadSiteStats() -{ - global $wgNumberOfArticles, $wgTotalViews, $wgTotalEdits; - if ( -1 != $wgNumberOfArticles ) return; - - $sql = 'SELECT ss_total_views, ss_total_edits, ss_good_articles ' . - 'FROM site_stats WHERE ss_row_id=1'; - $res = wfQuery( $sql, DB_READ, 'wfLoadSiteStats' ); - - if ( 0 == wfNumRows( $res ) ) { return; } - else { - $s = wfFetchObject( $res ); - $wgTotalViews = $s->ss_total_views; - $wgTotalEdits = $s->ss_total_edits; - $wgNumberOfArticles = $s->ss_good_articles; - } -} - -function wfEscapeHTML( $in ) -{ - return str_replace( - array( '&', '"', '>', '<' ), - array( '&', '"', '>', '<' ), - $in ); -} - -function wfEscapeHTMLTagsOnly( $in ) { - return str_replace( - array( '"', '>', '<' ), - array( '"', '>', '<' ), - $in ); -} - -function wfUnescapeHTML( $in ) -{ - $in = str_replace( '<', '<', $in ); - $in = str_replace( '>', '>', $in ); - $in = str_replace( '"', '"', $in ); - $in = str_replace( '&', '&', $in ); - return $in; -} - -function wfImageDir( $fname ) -{ - global $wgUploadDirectory; - - $hash = md5( $fname ); - $oldumask = umask(0); - $dest = $wgUploadDirectory . '/' . $hash{0}; - if ( ! is_dir( $dest ) ) { mkdir( $dest, 0777 ); } - $dest .= '/' . substr( $hash, 0, 2 ); - if ( ! is_dir( $dest ) ) { mkdir( $dest, 0777 ); } - - umask( $oldumask ); - return $dest; -} - -function wfImageThumbDir( $fname , $subdir='thumb') -{ - return wfImageArchiveDir( $fname, $subdir ); -} - -function wfImageArchiveDir( $fname , $subdir='archive') -{ - global $wgUploadDirectory; - - $hash = md5( $fname ); - $oldumask = umask(0); - - # Suppress warning messages here; if the file itself can't - # be written we'll worry about it then. - $archive = "{$wgUploadDirectory}/{$subdir}"; - if ( ! is_dir( $archive ) ) { @mkdir( $archive, 0777 ); } - $archive .= '/' . $hash{0}; - if ( ! is_dir( $archive ) ) { @mkdir( $archive, 0777 ); } - $archive .= '/' . substr( $hash, 0, 2 ); - if ( ! is_dir( $archive ) ) { @mkdir( $archive, 0777 ); } - - umask( $oldumask ); - return $archive; -} - -function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source = "" ) -{ - global $wgUser, $wgLang, $wgTitle, $wgOut, $wgDeferredUpdateList; - global $wgUseCopyrightUpload; - - $fname = 'wfRecordUpload'; - - $sql = 'SELECT img_name,img_size,img_timestamp,img_description,img_user,' . - "img_user_text FROM image WHERE img_name='" . wfStrencode( $name ) . "'"; - $res = wfQuery( $sql, DB_READ, $fname ); - - $now = wfTimestampNow(); - $won = wfInvertTimestamp( $now ); - $size = IntVal( $size ); - - if ( $wgUseCopyrightUpload ) - { - $textdesc = '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $desc . "\n" . - '== ' . wfMsg ( 'filestatus' ) . " ==\n" . $copyStatus . "\n" . - '== ' . wfMsg ( 'filesource' ) . " ==\n" . $source ; - } - else $textdesc = $desc ; - - $now = wfTimestampNow(); - $won = wfInvertTimestamp( $now ); - - if ( 0 == wfNumRows( $res ) ) { - $sql = 'INSERT INTO image (img_name,img_size,img_timestamp,' . - "img_description,img_user,img_user_text) VALUES ('" . - wfStrencode( $name ) . "',$size,'{$now}','" . - wfStrencode( $desc ) . "', '" . $wgUser->getID() . - "', '" . wfStrencode( $wgUser->getName() ) . "')"; - wfQuery( $sql, DB_WRITE, $fname ); - - $sql = 'SELECT cur_id,cur_text FROM cur WHERE cur_namespace=' . - Namespace::getImage() . " AND cur_title='" . - wfStrencode( $name ) . "'"; - $res = wfQuery( $sql, DB_READ, $fname ); - if ( 0 == wfNumRows( $res ) ) { - $common = - Namespace::getImage() . ",'" . - wfStrencode( $name ) . "','" . - wfStrencode( $desc ) . "','" . $wgUser->getID() . "','" . - wfStrencode( $wgUser->getName() ) . "','" . $now . - "',1"; - $sql = 'INSERT INTO cur (cur_namespace,cur_title,' . - 'cur_comment,cur_user,cur_user_text,cur_timestamp,cur_is_new,' . - 'cur_text,inverse_timestamp,cur_touched) VALUES (' . - $common . - ",'" . wfStrencode( $textdesc ) . "','{$won}','{$now}')"; - wfQuery( $sql, DB_WRITE, $fname ); - $id = wfInsertId() or 0; # We should throw an error instead - - $titleObj = Title::makeTitle( NS_IMAGE, $name ); - RecentChange::notifyNew( $now, $titleObj, 0, $wgUser, $desc ); - - $u = new SearchUpdate( $id, $name, $desc ); - $u->doUpdate(); - } - } else { - $s = wfFetchObject( $res ); - - $sql = 'INSERT INTO oldimage (oi_name,oi_archive_name,oi_size,' . - "oi_timestamp,oi_description,oi_user,oi_user_text) VALUES ('" . - wfStrencode( $s->img_name ) . "','" . - wfStrencode( $oldver ) . - "',{$s->img_size},'{$s->img_timestamp}','" . - wfStrencode( $s->img_description ) . "','" . - wfStrencode( $s->img_user ) . "','" . - wfStrencode( $s->img_user_text) . "')"; - wfQuery( $sql, DB_WRITE, $fname ); - - $sql = "UPDATE image SET img_size={$size}," . - "img_timestamp='" . wfTimestampNow() . "',img_user='" . - $wgUser->getID() . "',img_user_text='" . - wfStrencode( $wgUser->getName() ) . "', img_description='" . - wfStrencode( $desc ) . "' WHERE img_name='" . - wfStrencode( $name ) . "'"; - wfQuery( $sql, DB_WRITE, $fname ); - - $sql = "UPDATE cur SET cur_touched='{$now}' WHERE cur_namespace=" . - Namespace::getImage() . " AND cur_title='" . - wfStrencode( $name ) . "'"; - wfQuery( $sql, DB_WRITE, $fname ); - } - - $log = new LogPage( wfMsg( 'uploadlogpage' ), wfMsg( 'uploadlogpagetext' ) ); - $da = wfMsg( 'uploadedimage', '[[:' . $wgLang->getNsText( - Namespace::getImage() ) . ":{$name}|{$name}]]" ); - $ta = wfMsg( 'uploadedimage', $name ); - $log->addEntry( $da, $desc, $ta ); -} - /* Some generic result counters, pulled out of SearchEngine */ -function wfShowingResults( $offset, $limit ) -{ + +/** + * @todo document + */ +function wfShowingResults( $offset, $limit ) { global $wgLang; return wfMsg( 'showingresults', $wgLang->formatNum( $limit ), $wgLang->formatNum( $offset+1 ) ); } -function wfShowingResultsNum( $offset, $limit, $num ) -{ +/** + * @todo document + */ +function wfShowingResultsNum( $offset, $limit, $num ) { global $wgLang; return wfMsg( 'showingresultsnum', $wgLang->formatNum( $limit ), $wgLang->formatNum( $offset+1 ), $wgLang->formatNum( $num ) ); } -function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) -{ +/** + * @todo document + */ +function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) { global $wgUser, $wgLang; $fmtLimit = $wgLang->formatNum( $limit ); $prev = wfMsg( 'prevn', $fmtLimit ); @@ -620,13 +549,13 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) $po = $offset - $limit; if ( $po < 0 ) { $po = 0; } $q = "limit={$limit}&offset={$po}"; - if ( '' != $query ) { $q .= "&{$query}"; } + if ( '' != $query ) { $q .= '&'.$query; } $plink = '{$prev}"; } else { $plink = $prev; } $no = $offset + $limit; - $q = "limit={$limit}&offset={$no}"; - if ( "" != $query ) { $q .= "&{$query}"; } + $q = 'limit='.$limit.'&offset='.$no; + if ( '' != $query ) { $q .= '&'.$query; } if ( $atend ) { $nlink = $next; @@ -642,18 +571,26 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) return wfMsg( 'viewprevnext', $plink, $nlink, $nums ); } -function wfNumLink( $offset, $limit, $link, $query = '' ) -{ +/** + * @todo document + */ +function wfNumLink( $offset, $limit, $link, $query = '' ) { global $wgUser, $wgLang; if ( '' == $query ) { $q = ''; } - else { $q = "{$query}&"; } - $q .= "limit={$limit}&offset={$offset}"; + else { $q = $query.'&'; } + $q .= 'limit='.$limit.'&offset='.$offset; $fmtLimit = $wgLang->formatNum( $limit ); $s = '{$fmtLimit}"; return $s; } +/** + * @todo document + * @todo FIXME: we may want to blacklist some broken browsers + * + * @return bool Whereas client accept gzip compression + */ function wfClientAcceptsGzip() { global $wgUseGzip; if( $wgUseGzip ) { @@ -662,7 +599,7 @@ function wfClientAcceptsGzip() { '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/', $_SERVER['HTTP_ACCEPT_ENCODING'], $m ) ) { - if( ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) return false; + if( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) return false; wfDebug( " accepts gzip\n" ); return true; } @@ -670,42 +607,36 @@ function wfClientAcceptsGzip() { return false; } -# Yay, more global functions! +/** + * Yay, more global functions! + */ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) { - global $wgUser, $wgRequest; - - $limit = $wgRequest->getInt( 'limit', 0 ); - if( $limit < 0 ) $limit = 0; - if( ( $limit == 0 ) && ( $optionname != '' ) ) { - $limit = (int)$wgUser->getOption( $optionname ); - } - if( $limit <= 0 ) $limit = $deflimit; - if( $limit > 5000 ) $limit = 5000; # We have *some* limits... - - $offset = $wgRequest->getInt( 'offset', 0 ); - if( $offset < 0 ) $offset = 0; - if( $offset > 65000 ) $offset = 65000; # do we need a max? what? - - return array( $limit, $offset ); + global $wgRequest; + return $wgRequest->getLimitOffset( $deflimit, $optionname ); } -# Escapes the given text so that it may be output using addWikiText() -# without any linking, formatting, etc. making its way through. This -# is achieved by substituting certain characters with HTML entities. -# As required by the callers, is not used. It currently does -# not filter out characters which have special meaning only at the -# start of a line, such as "*". -function wfEscapeWikiText( $text ) -{ +/** + * Escapes the given text so that it may be output using addWikiText() + * without any linking, formatting, etc. making its way through. This + * is achieved by substituting certain characters with HTML entities. + * As required by the callers, is not used. It currently does + * not filter out characters which have special meaning only at the + * start of a line, such as "*". + * + * @param string $text Text to be escaped + */ +function wfEscapeWikiText( $text ) { $text = str_replace( - array( '[', '|', "'", 'ISBN ' , '://' , "\n=" ), - array( '[', '|', ''', 'ISBN ', '://' , "\n=" ), + array( '[', '|', "'", 'ISBN ' , '://' , "\n=", '{{' ), + array( '[', '|', ''', 'ISBN ', '://' , "\n=", '{{' ), htmlspecialchars($text) ); return $text; } -function wfQuotedPrintable( $string, $charset = '' ) -{ +/** + * @todo document + */ +function wfQuotedPrintable( $string, $charset = '' ) { # Probably incomplete; see RFC 2045 if( empty( $charset ) ) { global $wgInputEncoding; @@ -723,37 +654,57 @@ function wfQuotedPrintable( $string, $charset = '' ) return $out; } -function wfTime(){ +/** + * @todo document + * @return float + */ +function wfTime() { $st = explode( ' ', microtime() ); return (float)$st[0] + (float)$st[1]; } -# Changes the first character to an HTML entity +/** + * Changes the first character to an HTML entity + */ function wfHtmlEscapeFirst( $text ) { $ord = ord($text); $newText = substr($text, 1); return "&#$ord;$newText"; } -# Sets dest to source and returns the original value of dest -function wfSetVar( &$dest, $source ) -{ +/** + * Sets dest to source and returns the original value of dest + * If source is NULL, it just returns the value, it doesn't set the variable + */ +function wfSetVar( &$dest, $source ) { $temp = $dest; - $dest = $source; + if ( !is_null( $source ) ) { + $dest = $source; + } return $temp; } -# Sets dest to a reference to source and returns the original dest -# Pity that doesn't work in PHP -function &wfSetRef( &$dest, &$source ) -{ - die( "You can't rebind a variable in the caller's scope" ); +/** + * As for wfSetVar except setting a bit + */ +function wfSetBit( &$dest, $bit, $state = true ) { + $temp = (bool)($dest & $bit ); + if ( !is_null( $state ) ) { + if ( $state ) { + $dest |= $bit; + } else { + $dest &= ~$bit; + } + } + return $temp; } -# This function takes two arrays as input, and returns a CGI-style string, e.g. -# "days=7&limit=100". Options in the first array override options in the second. -# Options set to "" will not be output. -function wfArrayToCGI( $array1, $array2 = NULL ) +/** + * This function takes two arrays as input, and returns a CGI-style string, e.g. + * "days=7&limit=100". Options in the first array override options in the second. + * Options set to "" will not be output. + */ +function wfArrayToCGI( $array1, $array2 = NULL ) { if ( !is_null( $array2 ) ) { $array1 = $array1 + $array2; @@ -765,30 +716,36 @@ function wfArrayToCGI( $array1, $array2 = NULL ) if ( '' != $cgi ) { $cgi .= '&'; } - $cgi .= "{$key}={$value}"; + $cgi .= $key.'='.$value; } } return $cgi; } -# This is obsolete, use SquidUpdate::purge() +/** + * This is obsolete, use SquidUpdate::purge() + * @deprecated + */ function wfPurgeSquidServers ($urlArr) { SquidUpdate::purge( $urlArr ); } -# Windows-compatible version of escapeshellarg() -function wfEscapeShellArg( ) -{ +/** + * Windows-compatible version of escapeshellarg() + * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg() + * function puts single quotes in regardless of OS + */ +function wfEscapeShellArg( ) { $args = func_get_args(); $first = true; $retVal = ''; foreach ( $args as $arg ) { - if ( !$first ) { + if ( !$first ) { $retVal .= ' '; } else { $first = false; } - + if ( wfIsWindows() ) { $retVal .= '"' . str_replace( '"','\"', $arg ) . '"'; } else { @@ -798,15 +755,16 @@ function wfEscapeShellArg( ) return $retVal; } -# wfMerge attempts to merge differences between three texts. -# Returns true for a clean merge and false for failure or a conflict. - +/** + * wfMerge attempts to merge differences between three texts. + * Returns true for a clean merge and false for failure or a conflict. + */ function wfMerge( $old, $mine, $yours, &$result ){ global $wgDiff3; - # This check may also protect against code injection in + # This check may also protect against code injection in # case of broken installations. - if(! file_exists( $wgDiff3 ) ){ + if(! file_exists( $wgDiff3 ) ){ return false; } @@ -815,9 +773,9 @@ function wfMerge( $old, $mine, $yours, &$result ){ $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' ); $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' ); $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' ); - - fwrite( $oldtextFile, $old ); fclose( $oldtextFile ); - fwrite( $mytextFile, $mine ); fclose( $mytextFile ); + + fwrite( $oldtextFile, $old ); fclose( $oldtextFile ); + fwrite( $mytextFile, $mine ); fclose( $mytextFile ); fwrite( $yourtextFile, $yours ); fclose( $yourtextFile ); # Check for a conflict @@ -835,7 +793,7 @@ function wfMerge( $old, $mine, $yours, &$result ){ pclose( $handle ); # Merge differences - $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' . + $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' . wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName ); $handle = popen( $cmd, 'r' ); $result = ''; @@ -851,8 +809,10 @@ function wfMerge( $old, $mine, $yours, &$result ){ return ! $conflict; } -function wfVarDump( $var ) -{ +/** + * @todo document + */ +function wfVarDump( $var ) { global $wgOut; $s = str_replace("\n","
    \n", var_export( $var, true ) . "\n"); if ( headers_sent() || !@is_object( $wgOut ) ) { @@ -862,14 +822,16 @@ function wfVarDump( $var ) } } -# Provide a simple HTTP error. +/** + * Provide a simple HTTP error. + */ function wfHttpError( $code, $label, $desc ) { global $wgOut; $wgOut->disable(); header( "HTTP/1.0 $code $label" ); header( "Status: $code $label" ); $wgOut->sendCacheControl(); - + # Don't send content if it's a HEAD request. if( $_SERVER['REQUEST_METHOD'] == 'HEAD' ) { header( 'Content-type: text/plain' ); @@ -877,17 +839,20 @@ function wfHttpError( $code, $label, $desc ) { } } -# Converts an Accept-* header into an array mapping string values to quality factors +/** + * Converts an Accept-* header into an array mapping string values to quality + * factors + */ function wfAcceptToPrefs( $accept, $def = '*/*' ) { # No arg means accept anything (per HTTP spec) if( !$accept ) { return array( $def => 1 ); } - + $prefs = array(); - + $parts = explode( ',', $accept ); - + foreach( $parts as $part ) { # FIXME: doesn't deal with params like 'text/html; level=1' @list( $value, $qpart ) = explode( ';', $part ); @@ -897,11 +862,15 @@ function wfAcceptToPrefs( $accept, $def = '*/*' ) { $prefs[$value] = $match[1]; } } - + return $prefs; } -/* private */ function mimeTypeMatch( $type, $avail ) { +/** + * @todo document + * @private + */ +function mimeTypeMatch( $type, $avail ) { if( array_key_exists($type, $avail) ) { return $type; } else { @@ -916,11 +885,13 @@ function wfAcceptToPrefs( $accept, $def = '*/*' ) { } } -# FIXME: doesn't handle params like 'text/plain; charset=UTF-8' -# XXX: generalize to negotiate other stuff +/** + * @todo FIXME: doesn't handle params like 'text/plain; charset=UTF-8' + * XXX: generalize to negotiate other stuff + */ function wfNegotiateType( $cprefs, $sprefs ) { $combine = array(); - + foreach( array_keys($sprefs) as $type ) { $parts = explode( '/', $type ); if( $parts[1] != '*' ) { @@ -930,7 +901,7 @@ function wfNegotiateType( $cprefs, $sprefs ) { } } } - + foreach( array_keys( $cprefs ) as $type ) { $parts = explode( '/', $type ); if( $parts[1] != '*' && !array_key_exists( $type, $sprefs ) ) { @@ -940,36 +911,153 @@ function wfNegotiateType( $cprefs, $sprefs ) { } } } - + $bestq = 0; $besttype = NULL; - + foreach( array_keys( $combine ) as $type ) { if( $combine[$type] > $bestq ) { $besttype = $type; $bestq = $combine[$type]; } } - + return $besttype; } -# Array lookup -# Returns an array where the values in the first array are replaced by the -# values in the second array with the corresponding keys -function wfArrayLookup( $a, $b ) -{ - return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) ); +/** + * Array lookup + * Returns an array where the values in the first array are replaced by the + * values in the second array with the corresponding keys + * + * @return array + */ +function wfArrayLookup( $a, $b ) { + return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) ); +} + + +/** + * Ideally we'd be using actual time fields in the db + * @todo fixme + */ +function wfTimestamp2Unix( $ts ) { + return gmmktime( ( (int)substr( $ts, 8, 2) ), + (int)substr( $ts, 10, 2 ), (int)substr( $ts, 12, 2 ), + (int)substr( $ts, 4, 2 ), (int)substr( $ts, 6, 2 ), + (int)substr( $ts, 0, 4 ) ); +} + +/** + * @todo document + */ +function wfUnix2Timestamp( $unixtime ) { + return gmdate( 'YmdHis', $unixtime ); } -# Since Windows is so different to any of the other popular OSes, it seems appropriate -# to have a simple way to test for its presence -function wfIsWindows() { - if (substr(php_uname(), 0, 7) == 'Windows') { - return true; +/** + * @todo document + */ +function wfTimestampNow() { + # return NOW + return gmdate( 'YmdHis' ); +} + +/** + * Sorting hack for MySQL 3, which doesn't use index sorts for DESC + */ +function wfInvertTimestamp( $ts ) { + return strtr( + $ts, + '0123456789', + '9876543210' + ); +} + +/** + * Reference-counted warning suppression + */ +function wfSuppressWarnings( $end = false ) { + static $suppressCount = 0; + static $originalLevel = false; + + if ( $end ) { + if ( $suppressCount ) { + $suppressCount --; + if ( !$suppressCount ) { + error_reporting( $originalLevel ); + } + } } else { - return false; + if ( !$suppressCount ) { + $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE ) ); + } + $suppressCount++; } } +/** + * Restore error level to previous value + */ +function wfRestoreWarnings() { + wfSuppressWarnings( true ); +} + +# Autodetect, convert and provide timestamps of various types + +/** Standard unix timestamp (number of seconds since 1 Jan 1970) */ +define('TS_UNIX',0); +/** MediaWiki concatenated string timestamp (yyyymmddhhmmss) */ +define('TS_MW',1); +/** Standard database timestamp (yyyy-mm-dd hh:mm:ss) */ +define('TS_DB',2); + +/** + * @todo document + */ +function wfTimestamp($outputtype=TS_UNIX,$ts=0) { + if (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) { + # TS_DB + $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], + (int)$da[2],(int)$da[3],(int)$da[1]); + } elseif (preg_match("/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/",$ts,$da)) { + # TS_MW + $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], + (int)$da[2],(int)$da[3],(int)$da[1]); + } elseif (preg_match("/^(\d{1,13})$/",$ts,$datearray)) { + # TS_UNIX + $uts=$ts; + } + + if ($ts==0) + $uts=time(); + switch($outputtype) { + case TS_UNIX: + return $uts; + break; + case TS_MW: + return gmdate( 'YmdHis', $uts ); + break; + case TS_DB: + return gmdate( 'Y-m-d H:i:s', $uts ); + break; + default: + return; + } +} + +/** + * Check where as the operating system is Windows + * + * @todo document + * @return bool True if it's windows, False otherwise. + */ +function wfIsWindows() { + if (substr(php_uname(), 0, 7) == 'Windows') { + return true; + } else { + return false; + } +} + ?>