X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;ds=sidebyside;f=includes%2FGlobalFunctions.php;h=31b72a760b71e36c514376258863637b22f570df;hb=3825e915befb0d0394bf3e5e120f3ba759cc9bf3;hp=6cc035173641e6219ba2d14c2efebd953278cbfd;hpb=a8a113d22dd8f8a17febd64131838a8fec4798df;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 6cc0351736..31b72a760b 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1,5 +1,4 @@ = 3) { - $end = func_get_arg(2); - return join("",array_slice($ar[0],$start,$end)); + if( func_num_args() >= 3 ) { + $end = func_get_arg( 2 ); + return join( '', array_slice( $ar[0], $start, $end ) ); } else { - return join("",array_slice($ar[0],$start)); + return join( '', array_slice( $ar[0], $start ) ); } } } @@ -89,17 +88,43 @@ if ( !function_exists( 'mb_substr' ) ) { * @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' ) { + $fname = 'do_html_entity_decode'; + wfProfileIn( $fname ); + static $trans; - if( !isset( $trans ) ) { + static $savedCharset; + static $regexp; + if( !isset( $trans ) || $savedCharset != $charset ) { $trans = array_flip( get_html_translation_table( HTML_ENTITIES, $quote_style ) ); - # Assumes $charset will always be the same through a run, and only understands - # utf-8 or default. Note - mixing latin1 named entities and unicode numbered + $savedCharset = $charset; + + # Note - mixing latin1 named entities and unicode numbered # ones will result in a bad link. if( strcasecmp( 'utf-8', $charset ) == 0 ) { $trans = array_map( 'utf8_encode', $trans ); } + + /** + * Most links will _not_ contain these fun guys, + * and on long pages with many links we can get + * called a lot. + * + * A regular expression search is faster than + * a strtr or str_replace with a hundred-ish + * entries, though it may be slower to actually + * replace things. + * + * They all look like '&xxxx;'... + */ + foreach( $trans as $key => $val ) { + $snip[] = substr( $key, 1, -1 ); + } + $regexp = '/(&(?:' . implode( '|', $snip ) . ');)/e'; } - return strtr( $string, $trans ); + + $out = preg_replace( $regexp, '$trans["$1"]', $string ); + wfProfileOut( $fname ); + return $out; } @@ -126,42 +151,19 @@ function wfSeedRandom() { } /** - * Generates a URL from a URL-encoded title and a query string - * Title::getLocalURL() is preferred in most cases + * Get a random decimal value between 0 and 1, in a way + * not likely to give duplicate values for any realistic + * number of articles. * - * @param string $a URL encoded title - * @param string $q URL (default '') - */ -function wfLocalUrl( $a, $q = '' ) { - global $wgServer, $wgScript, $wgArticlePath; - - $a = str_replace( ' ', '_', $a ); - - if ( '' == $a ) { - if( '' == $q ) { - $a = $wgScript; - } else { - $a = $wgScript.'?'.$q; - } - } else if ( '' == $q ) { - $a = str_replace( '$1', $a, $wgArticlePath ); - } else if ($wgScript != '' ) { - $a = "{$wgScript}?title={$a}&{$q}"; - } else { //XXX hackish solution for toplevel wikis - $a = "/{$a}?{$q}"; - } - return $a; -} - -/** - * @todo document - * @param string $a URL encoded title - * @param string $q URL (default '') + * @return string */ -function wfLocalUrlE( $a, $q = '' ) -{ - return htmlspecialchars( wfLocalUrl( $a, $q ) ); - # die( "Call to obsolete function wfLocalUrlE()" ); +function wfRandom() { + # The maximum random value is "only" 2^31-1, so get two random + # values to reduce the chance of dupes + $max = mt_getrandmax(); + $rand = number_format( mt_rand() * mt_rand() + / $max / $max, 12, '.', '' ); + return $rand; } /** @@ -225,38 +227,8 @@ function wfMungeToUtf8( $string ) { * */ function wfUtf8Entity( $matches ) { - $char = $matches[0]; - # Find the length - $z = ord( $char{0} ); - if ( $z & 0x80 ) { - $length = 0; - while ( $z & 0x80 ) { - $length++; - $z <<= 1; - } - } else { - $length = 1; - } - - if ( $length != strlen( $char ) ) { - return ''; - } - if ( $length == 1 ) { - return $char; - } - - # Mask off the length-determining bits and shift back to the original location - $z &= 0xff; - $z >>= $length; - - # Add in the free bits from subsequent bytes - for ( $i=1; $i<$length; $i++ ) { - $z <<= 6; - $z |= ord( $char{$i} ) & 0x3f; - } - - # Make entity - return "&#$z;"; + $codepoint = utf8ToCodepoint( $matches[0] ); + return "&#$codepoint;"; } /** @@ -268,7 +240,17 @@ function wfUtf8ToHTML($string) { } /** - * @todo document + * Sends a line to the debug log if enabled or, optionally, to a comment in output. + * In normal operation this is a NOP. + * + * Controlling globals: + * $wgDebugLogFile - points to the log file + * $wgProfileOnly - if set, normal debug messages will not be recorded. + * $wgDebugRawPage - if false, 'action=raw' hits will not result in debug output. + * $wgDebugComments - if on, some debug items may appear in comments in the HTML output. + * + * @param string $text + * @param bool $logonly Set true to avoid appearing in HTML when $wgDebugComments is set */ function wfDebug( $text, $logonly = false ) { global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage; @@ -320,7 +302,7 @@ function logProfilingData() { $forward .= ' from ' . $_SERVER['HTTP_FROM']; if( $forward ) $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})"; - if($wgUser->getId() == 0) + if( $wgUser->isAnon() ) $forward .= ' anon'; $log = sprintf( "%s\t%04.3f\t%s\n", gmdate( 'YmdHis' ), $elapsed, @@ -346,28 +328,13 @@ function wfReadOnly() { return is_file( $wgReadOnlyFile ); } -/** - * Keys strings for replacement - * @global array $wgReplacementKeys - */ -$wgReplacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' ); /** * Get a message from anywhere, for the UI elements */ 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 ); - } + array_shift( $args ); return wfMsgReal( $key, $args, true ); } @@ -375,20 +342,14 @@ function wfMsg( $key ) { * Get a message from anywhere, for the content */ function wfMsgForContent( $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; - } + global $wgForceUIMsgAsContentMsg; $args = func_get_args(); - if ( count( $args ) ) { - array_shift( $args ); - } - return wfMsgReal( $key, $args, true, true ); - - + array_shift( $args ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, true, $forcontent ); } /** @@ -396,9 +357,7 @@ function wfMsgForContent( $key ) { */ function wfMsgNoDB( $key ) { $args = func_get_args(); - if ( count( $args ) ) { - array_shift( $args ); - } + array_shift( $args ); return wfMsgReal( $key, $args, false ); } @@ -406,12 +365,14 @@ function wfMsgNoDB( $key ) { * Get a message from the language file, for the content */ function wfMsgNoDBForContent( $key ) { - + global $wgForceUIMsgAsContentMsg; $args = func_get_args(); - if ( count( $args ) ) { - array_shift( $args ); - } - return wfMsgReal( $key, $args, false, true ); + array_shift( $args ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, false, $forcontent ); } @@ -419,45 +380,41 @@ function wfMsgNoDBForContent( $key ) { * Really get a message */ function wfMsgReal( $key, $args, $useDB, $forContent=false ) { - global $wgReplacementKeys, $wgParser, $wgMsgParserOptions; + static $replacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' ); + global $wgParser, $wgMsgParserOptions; global $wgContLang, $wgLanguageCode; - if($forContent) { - global $wgMessageCache; - $cache = &$wgMessageCache; - $lang = &$wgContLang; + global $wgMessageCache, $wgLang; + + $fname = 'wfMsgReal'; + wfProfileIn( $fname ); + + if( is_object( $wgMessageCache ) ) { + $message = $wgMessageCache->get( $key, $useDB, $forContent ); } - else { - if(in_array($wgLanguageCode, $wgContLang->getVariants())){ - global $wgLang, $wgMessageCache; - $cache = &$wgMessageCache; - $lang = $wgLang; - } - else { - global $wgLang; - $cache = false; - $lang = &$wgLang; + else { + if( $forContent ) { + $lang = &$wgContLang; + } else { + $lang = &$wgLang; } - } - $fname = 'wfMsg'; - wfProfileIn( $fname ); - if ( is_object($cache) ) { - $message = $cache->get( $key, $useDB, $forContent ); - } elseif (is_object($lang)) { - $message = $lang->getMessage( $key ); + wfSuppressWarnings(); + if( is_object( $lang ) ) { + $message = $lang->getMessage( $key ); + } else { + $message = ''; + } + wfRestoreWarnings(); if(!$message) $message = Language::getMessage($key); if(strstr($message, '{{' ) !== false) { $message = $wgParser->transformMsg($message, $wgMsgParserOptions); } - } else { - wfDebug( "No language object when getting $key\n" ); - $message = "<$key>"; } # Replace arguments if( count( $args ) ) { - $message = str_replace( $wgReplacementKeys, $args, $message ); + $message = str_replace( $replacementKeys, $args, $message ); } wfProfileOut( $fname ); return $message; @@ -518,12 +475,21 @@ function wfDebugDieBacktrace( $msg = '' ) { } $backtrace = debug_backtrace(); foreach( $backtrace as $call ) { - $f = explode( DIRECTORY_SEPARATOR, $call['file'] ); - $file = $f[count($f)-1]; + if( isset( $call['file'] ) ) { + $f = explode( DIRECTORY_SEPARATOR, $call['file'] ); + $file = $f[count($f)-1]; + } else { + $file = '-'; + } + if( isset( $call['line'] ) ) { + $line = $call['line']; + } else { + $line = '-'; + } if ( $wgCommandLineMode ) { - $msg .= "$file line {$call['line']} calls "; + $msg .= "$file line $line calls "; } else { - $msg .= '
  • ' . $file . ' line ' . $call['line'] . ' calls '; + $msg .= '
  • ' . $file . ' line ' . $line . ' calls '; } if( !empty( $call['class'] ) ) $msg .= $call['class'] . '::'; $msg .= $call['function'] . '()'; @@ -566,15 +532,23 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) { $fmtLimit = $wgLang->formatNum( $limit ); $prev = wfMsg( 'prevn', $fmtLimit ); $next = wfMsg( 'nextn', $fmtLimit ); - $link = wfUrlencode( $link ); - + + if( is_object( $link ) ) { + $title =& $link; + } else { + $title =& Title::newFromText( $link ); + if( is_null( $title ) ) { + return false; + } + } + $sk = $wgUser->getSkin(); if ( 0 != $offset ) { $po = $offset - $limit; if ( $po < 0 ) { $po = 0; } $q = "limit={$limit}&offset={$po}"; if ( '' != $query ) { $q .= '&'.$query; } - $plink = '{$prev}"; + $plink = '{$prev}"; } else { $plink = $prev; } $no = $offset + $limit; @@ -584,13 +558,13 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) { if ( $atend ) { $nlink = $next; } else { - $nlink = '{$next}"; + $nlink = '{$next}"; } - $nums = wfNumLink( $offset, 20, $link , $query ) . ' | ' . - wfNumLink( $offset, 50, $link, $query ) . ' | ' . - wfNumLink( $offset, 100, $link, $query ) . ' | ' . - wfNumLink( $offset, 250, $link, $query ) . ' | ' . - wfNumLink( $offset, 500, $link, $query ); + $nums = wfNumLink( $offset, 20, $title, $query ) . ' | ' . + wfNumLink( $offset, 50, $title, $query ) . ' | ' . + wfNumLink( $offset, 100, $title, $query ) . ' | ' . + wfNumLink( $offset, 250, $title, $query ) . ' | ' . + wfNumLink( $offset, 500, $title, $query ); return wfMsg( 'viewprevnext', $plink, $nlink, $nums ); } @@ -598,14 +572,14 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) { /** * @todo document */ -function wfNumLink( $offset, $limit, $link, $query = '' ) { +function wfNumLink( $offset, $limit, &$title, $query = '' ) { global $wgUser, $wgLang; if ( '' == $query ) { $q = ''; } else { $q = $query.'&'; } $q .= 'limit='.$limit.'&offset='.$offset; $fmtLimit = $wgLang->formatNum( $limit ); - $s = '{$fmtLimit}"; + $s = '{$fmtLimit}"; return $s; } @@ -651,7 +625,7 @@ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) { */ function wfEscapeWikiText( $text ) { $text = str_replace( - array( '[', '|', "'", 'ISBN ' , '://' , "\n=", '{{' ), + array( '[', '|', '\'', 'ISBN ' , '://' , "\n=", '{{' ), array( '[', '|', ''', 'ISBN ', '://' , "\n=", '{{' ), htmlspecialchars($text) ); return $text; @@ -740,7 +714,7 @@ function wfArrayToCGI( $array1, $array2 = NULL ) if ( '' != $cgi ) { $cgi .= '&'; } - $cgi .= $key.'='.$value; + $cgi .= urlencode( $key ) . '=' . urlencode( $value ); } } return $cgi; @@ -809,7 +783,7 @@ function wfMerge( $old, $mine, $yours, &$result ){ wfEscapeShellArg( $yourtextName ); $handle = popen( $cmd, 'r' ); - if( fgets( $handle ) ){ + if( fgets( $handle, 1024 ) ){ $conflict = true; } else { $conflict = false; @@ -838,7 +812,7 @@ function wfMerge( $old, $mine, $yours, &$result ){ */ function wfVarDump( $var ) { global $wgOut; - $s = str_replace("\n","
    \n", var_export( $var, true ) . "\n"); + $s = str_replace("\n","
    \n", var_export( $var, true ) . "\n"); if ( headers_sent() || !@is_object( $wgOut ) ) { print $s; } else { @@ -859,7 +833,7 @@ function wfHttpError( $code, $label, $desc ) { # Don't send content if it's a HEAD request. if( $_SERVER['REQUEST_METHOD'] == 'HEAD' ) { header( 'Content-type: text/plain' ); - print "$desc\n"; + print $desc."\n"; } } @@ -891,8 +865,16 @@ function wfAcceptToPrefs( $accept, $def = '*/*' ) { } /** - * @todo document - * @private + * Checks if a given MIME type matches any of the keys in the given + * array. Basic wildcards are accepted in the array keys. + * + * Returns the matching MIME type (or wildcard) if a match, otherwise + * NULL if no match. + * + * @param string $type + * @param array $avail + * @return string + * @access private */ function mimeTypeMatch( $type, $avail ) { if( array_key_exists($type, $avail) ) { @@ -910,6 +892,15 @@ function mimeTypeMatch( $type, $avail ) { } /** + * Returns the 'best' match between a client's requested internet media types + * and the server's list of available types. Each list should be an associative + * array of type to preference (preference is a float between 0.0 and 1.0). + * Wildcards in the types are acceptable. + * + * @param array $cprefs Client's acceptable type list + * @param array $sprefs Server's offered types + * @return string + * * @todo FIXME: doesn't handle params like 'text/plain; charset=UTF-8' * XXX: generalize to negotiate other stuff */ @@ -960,42 +951,13 @@ 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 ); -} - -/** - * @todo document + * Convenience function; returns MediaWiki timestamp for the present time. + * @return string */ 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' - ); + return wfTimestamp( TS_MW, time() ); } /** @@ -1035,6 +997,8 @@ define('TS_UNIX',0); define('TS_MW',1); /** Standard database timestamp (yyyy-mm-dd hh:mm:ss) */ define('TS_DB',2); +/** For HTTP and e-mail headers -- output only */ +define('TS_RFC2822', 3 ); /** * @todo document @@ -1051,6 +1015,10 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { } elseif (preg_match("/^(\d{1,13})$/",$ts,$datearray)) { # TS_UNIX $uts=$ts; + } else { + # Bogus value; fall back to the epoch... + wfDebug("wfTimestamp() given bogus time value.\n"); + $uts = 0; } if ($ts==0) @@ -1058,15 +1026,14 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { 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; + case TS_RFC2822: + return gmdate( 'D, d M Y H:i:s', $uts ) . ' GMT'; default: - return; + wfDebugDieBacktrace( 'wfTimestamp() called with illegal output type.'); } } @@ -1084,4 +1051,37 @@ function wfIsWindows() { } } +/** + * Swap two variables + */ +function swap( &$x, &$y ) { + $z = $x; + $x = $y; + $y = $z; +} + +function wfGetSiteNotice() { + global $wgSiteNotice, $wgTitle, $wgOut; + $fname = 'wfGetSiteNotice'; + wfProfileIn( $fname ); + + $notice = wfMsg( 'sitenotice' ); + if($notice == '<sitenotice>') $notice = ''; + # Allow individual wikis to turn it off + if ( $notice == '-' ) { + $notice = ''; + } else { + if ($notice == '') { + $notice = $wgSiteNotice; + } + if($notice != '-' && $notice != '') { + $specialparser = new Parser(); + $parserOutput = $specialparser->parse( $notice, $wgTitle, $wgOut->mParserOptions, false ); + $notice = $parserOutput->getText(); + } + } + wfProfileOut( $fname ); + return $notice; +} + ?>