From d9022f63880ce039446fba8364f68e656b7bf4cb Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Thu, 3 May 2012 13:01:35 +0200 Subject: Update to MediaWiki 1.19.0 --- includes/GlobalFunctions.php | 1111 ++++++++++++++++++++++++------------------ 1 file changed, 649 insertions(+), 462 deletions(-) (limited to 'includes/GlobalFunctions.php') diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 8ed79c40..52cd46a5 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -81,6 +81,9 @@ if ( !function_exists( 'istainted' ) ) { /** * Like array_diff( $a, $b ) except that it works with two-dimensional arrays. + * @param $a array + * @param $b array + * @return array */ function wfArrayDiff2( $a, $b ) { return array_udiff( $a, $b, 'wfArrayDiff2_cmp' ); @@ -164,7 +167,7 @@ function wfArrayMerge( $array1/* ... */ ) { * array( array( 'x' ) ), * array( array( 'x', '2' ) ), * array( array( 'x' ) ), - * array( array( 'y') ) + * array( array( 'y' ) ) * ); * returns: * array( @@ -296,9 +299,9 @@ function wfUrlencode( $s ) { static $needle; if ( is_null( $s ) ) { $needle = null; - return; + return ''; } - + if ( is_null( $needle ) ) { $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' ); if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) || ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false ) ) { @@ -319,7 +322,7 @@ function wfUrlencode( $s ) { /** * 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. + * Options set to null or false will not be output. * * @param $array1 Array ( String|Array ) * @param $array2 Array ( String|Array ) @@ -333,7 +336,7 @@ function wfArrayToCGI( $array1, $array2 = null, $prefix = '' ) { $cgi = ''; foreach ( $array1 as $key => $value ) { - if ( $value !== '' ) { + if ( !is_null($value) && $value !== false ) { if ( $cgi != '' ) { $cgi .= '&'; } @@ -366,8 +369,7 @@ function wfArrayToCGI( $array1, $array2 = null, $prefix = '' ) { * This is the logical opposite of wfArrayToCGI(): it accepts a query string as * its argument and returns the same string in array form. This allows compa- * tibility with legacy functions that accept raw query strings instead of nice - * arrays. Of course, keys and values are urldecode()d. Don't try passing in- - * valid query strings, or it will explode. + * arrays. Of course, keys and values are urldecode()d. * * @param $query String: query string * @return array Array version of input @@ -382,7 +384,13 @@ function wfCgiToArray( $query ) { if ( $bit === '' ) { continue; } - list( $key, $value ) = explode( '=', $bit ); + if ( strpos( $bit, '=' ) === false ) { + // Pieces like &qwerty become 'qwerty' => '' (at least this is what php does) + $key = $bit; + $value = ''; + } else { + list( $key, $value ) = explode( '=', $bit ); + } $key = urldecode( $key ); $value = urldecode( $value ); if ( strpos( $key, '[' ) !== false ) { @@ -444,8 +452,11 @@ function wfAppendQuery( $url, $query ) { * like "subdir/foo.html", etc. * * @param $url String: either fully-qualified or a local path + query - * @param $defaultProto Mixed: one of the PROTO_* constants. Determines the protocol to use if $url or $wgServer is protocol-relative - * @return string Fully-qualified URL + * @param $defaultProto Mixed: one of the PROTO_* constants. Determines the + * protocol to use if $url or $wgServer is + * protocol-relative + * @return string Fully-qualified URL, current-path-relative URL or false if + * no valid URL can be constructed */ function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) { global $wgServer, $wgCanonicalServer, $wgInternalServer; @@ -477,21 +488,170 @@ function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) { $defaultProtoWithoutSlashes = substr( $defaultProto, 0, -2 ); - if( substr( $url, 0, 2 ) == '//' ) { - return $defaultProtoWithoutSlashes . $url; - } elseif( substr( $url, 0, 1 ) == '/' ) { + if ( substr( $url, 0, 2 ) == '//' ) { + $url = $defaultProtoWithoutSlashes . $url; + } elseif ( substr( $url, 0, 1 ) == '/' ) { // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes, otherwise leave it alone - return ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url; - } else { + $url = ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url; + } + + $bits = wfParseUrl( $url ); + if ( $bits && isset( $bits['path'] ) ) { + $bits['path'] = wfRemoveDotSegments( $bits['path'] ); + return wfAssembleUrl( $bits ); + } elseif ( $bits ) { + # No path to expand return $url; + } elseif ( substr( $url, 0, 1 ) != '/' ) { + # URL is a relative path + return wfRemoveDotSegments( $url ); + } + + # Expanded URL is not valid. + return false; +} + +/** + * This function will reassemble a URL parsed with wfParseURL. This is useful + * if you need to edit part of a URL and put it back together. + * + * This is the basic structure used (brackets contain keys for $urlParts): + * [scheme][delimiter][user]:[pass]@[host]:[port][path]?[query]#[fragment] + * + * @todo Need to integrate this into wfExpandUrl (bug 32168) + * + * @since 1.19 + * @param $urlParts Array URL parts, as output from wfParseUrl + * @return string URL assembled from its component parts + */ +function wfAssembleUrl( $urlParts ) { + $result = ''; + + if ( isset( $urlParts['delimiter'] ) ) { + if ( isset( $urlParts['scheme'] ) ) { + $result .= $urlParts['scheme']; + } + + $result .= $urlParts['delimiter']; + } + + if ( isset( $urlParts['host'] ) ) { + if ( isset( $urlParts['user'] ) ) { + $result .= $urlParts['user']; + if ( isset( $urlParts['pass'] ) ) { + $result .= ':' . $urlParts['pass']; + } + $result .= '@'; + } + + $result .= $urlParts['host']; + + if ( isset( $urlParts['port'] ) ) { + $result .= ':' . $urlParts['port']; + } } + + if ( isset( $urlParts['path'] ) ) { + $result .= $urlParts['path']; + } + + if ( isset( $urlParts['query'] ) ) { + $result .= '?' . $urlParts['query']; + } + + if ( isset( $urlParts['fragment'] ) ) { + $result .= '#' . $urlParts['fragment']; + } + + return $result; +} + +/** + * Remove all dot-segments in the provided URL path. For example, + * '/a/./b/../c/' becomes '/a/c/'. For details on the algorithm, please see + * RFC3986 section 5.2.4. + * + * @todo Need to integrate this into wfExpandUrl (bug 32168) + * + * @param $urlPath String URL path, potentially containing dot-segments + * @return string URL path with all dot-segments removed + */ +function wfRemoveDotSegments( $urlPath ) { + $output = ''; + $inputOffset = 0; + $inputLength = strlen( $urlPath ); + + while ( $inputOffset < $inputLength ) { + $prefixLengthOne = substr( $urlPath, $inputOffset, 1 ); + $prefixLengthTwo = substr( $urlPath, $inputOffset, 2 ); + $prefixLengthThree = substr( $urlPath, $inputOffset, 3 ); + $prefixLengthFour = substr( $urlPath, $inputOffset, 4 ); + $trimOutput = false; + + if ( $prefixLengthTwo == './' ) { + # Step A, remove leading "./" + $inputOffset += 2; + } elseif ( $prefixLengthThree == '../' ) { + # Step A, remove leading "../" + $inputOffset += 3; + } elseif ( ( $prefixLengthTwo == '/.' ) && ( $inputOffset + 2 == $inputLength ) ) { + # Step B, replace leading "/.$" with "/" + $inputOffset += 1; + $urlPath[$inputOffset] = '/'; + } elseif ( $prefixLengthThree == '/./' ) { + # Step B, replace leading "/./" with "/" + $inputOffset += 2; + } elseif ( $prefixLengthThree == '/..' && ( $inputOffset + 3 == $inputLength ) ) { + # Step C, replace leading "/..$" with "/" and + # remove last path component in output + $inputOffset += 2; + $urlPath[$inputOffset] = '/'; + $trimOutput = true; + } elseif ( $prefixLengthFour == '/../' ) { + # Step C, replace leading "/../" with "/" and + # remove last path component in output + $inputOffset += 3; + $trimOutput = true; + } elseif ( ( $prefixLengthOne == '.' ) && ( $inputOffset + 1 == $inputLength ) ) { + # Step D, remove "^.$" + $inputOffset += 1; + } elseif ( ( $prefixLengthTwo == '..' ) && ( $inputOffset + 2 == $inputLength ) ) { + # Step D, remove "^..$" + $inputOffset += 2; + } else { + # Step E, move leading path segment to output + if ( $prefixLengthOne == '/' ) { + $slashPos = strpos( $urlPath, '/', $inputOffset + 1 ); + } else { + $slashPos = strpos( $urlPath, '/', $inputOffset ); + } + if ( $slashPos === false ) { + $output .= substr( $urlPath, $inputOffset ); + $inputOffset = $inputLength; + } else { + $output .= substr( $urlPath, $inputOffset, $slashPos - $inputOffset ); + $inputOffset += $slashPos - $inputOffset; + } + } + + if ( $trimOutput ) { + $slashPos = strrpos( $output, '/' ); + if ( $slashPos === false ) { + $output = ''; + } else { + $output = substr( $output, 0, $slashPos ); + } + } + } + + return $output; } /** * Returns a regular expression of url protocols * * @param $includeProtocolRelative bool If false, remove '//' from the returned protocol list. - * DO NOT USE this directy, use wfUrlProtocolsWithoutProtRel() instead + * DO NOT USE this directly, use wfUrlProtocolsWithoutProtRel() instead * @return String */ function wfUrlProtocols( $includeProtocolRelative = true ) { @@ -537,6 +697,7 @@ function wfUrlProtocols( $includeProtocolRelative = true ) { * Like wfUrlProtocols(), but excludes '//' from the protocol list. Use this if * you need a regex that matches all URL protocols but does not match protocol- * relative URLs + * @return String */ function wfUrlProtocolsWithoutProtRel() { return wfUrlProtocols( false ); @@ -554,7 +715,7 @@ function wfUrlProtocolsWithoutProtRel() { */ function wfParseUrl( $url ) { global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php - + // Protocol-relative URLs are handled really badly by parse_url(). It's so bad that the easiest // way to handle them is to just prepend 'http:' and strip the protocol out later $wasRelative = substr( $url, 0, 2 ) == '//'; @@ -564,7 +725,9 @@ function wfParseUrl( $url ) { wfSuppressWarnings(); $bits = parse_url( $url ); wfRestoreWarnings(); - if ( !$bits ) { + // parse_url() returns an array without scheme for some invalid URLs, e.g. + // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' ) + if ( !$bits || !isset( $bits['scheme'] ) ) { return false; } @@ -592,7 +755,7 @@ function wfParseUrl( $url ) { $bits['path'] = '/' . $bits['path']; } } - + // If the URL was protocol-relative, fix scheme and delimiter if ( $wasRelative ) { $bits['scheme'] = ''; @@ -717,6 +880,8 @@ function wfDebug( $text, $logonly = false ) { wfErrorLog( $text, $wgDebugLogFile ); } } + + MWDebug::debugMsg( $text ); } /** @@ -747,20 +912,15 @@ function wfIsDebugRawPage() { * @return string */ function wfDebugTimer() { - global $wgDebugTimestamps; + global $wgDebugTimestamps, $wgRequestTime; + if ( !$wgDebugTimestamps ) { return ''; } - static $start = null; - - if ( $start === null ) { - $start = microtime( true ); - $prefix = "\n$start"; - } else { - $prefix = sprintf( "%6.4f", microtime( true ) - $start ); - } - return $prefix . ' '; + $prefix = sprintf( "%6.4f", microtime( true ) - $wgRequestTime ); + $mem = sprintf( "%5.1fM", ( memory_get_usage( true ) / ( 1024 * 1024 ) ) ); + return "$prefix $mem "; } /** @@ -788,16 +948,12 @@ function wfDebugMem( $exact = false ) { * log file is specified, (default true) */ function wfDebugLog( $logGroup, $text, $public = true ) { - global $wgDebugLogGroups, $wgShowHostnames; + global $wgDebugLogGroups; $text = trim( $text ) . "\n"; if( isset( $wgDebugLogGroups[$logGroup] ) ) { $time = wfTimestamp( TS_DB ); $wiki = wfWikiID(); - if ( $wgShowHostnames ) { - $host = wfHostname(); - } else { - $host = ''; - } + $host = wfHostname(); if ( wfRunHooks( 'Debug', array( $text, $logGroup ) ) ) { wfErrorLog( "$time $host $wiki: $text", $wgDebugLogGroups[$logGroup] ); } @@ -812,14 +968,97 @@ function wfDebugLog( $logGroup, $text, $public = true ) { * @param $text String: database error message. */ function wfLogDBError( $text ) { - global $wgDBerrorLog, $wgDBname; + global $wgDBerrorLog; if ( $wgDBerrorLog ) { - $host = trim(`hostname`); - $text = date( 'D M j G:i:s T Y' ) . "\t$host\t$wgDBname\t$text"; + $host = wfHostname(); + $wiki = wfWikiID(); + $text = date( 'D M j G:i:s T Y' ) . "\t$host\t$wiki\t$text"; wfErrorLog( $text, $wgDBerrorLog ); } } +/** + * Throws a warning that $function is deprecated + * + * @param $function String + * @param $version String|false: Added in 1.19. + * @param $component String|false: Added in 1.19. + * + * @return null + */ +function wfDeprecated( $function, $version = false, $component = false ) { + static $functionsWarned = array(); + + MWDebug::deprecated( $function, $version, $component ); + + if ( !isset( $functionsWarned[$function] ) ) { + $functionsWarned[$function] = true; + + if ( $version ) { + global $wgDeprecationReleaseLimit; + + if ( $wgDeprecationReleaseLimit && $component === false ) { + # Strip -* off the end of $version so that branches can use the + # format #.##-branchname to avoid issues if the branch is merged into + # a version of MediaWiki later than what it was branched from + $comparableVersion = preg_replace( '/-.*$/', '', $version ); + + # If the comparableVersion is larger than our release limit then + # skip the warning message for the deprecation + if ( version_compare( $wgDeprecationReleaseLimit, $comparableVersion, '<' ) ) { + return; + } + } + + $component = $component === false ? 'MediaWiki' : $component; + wfWarn( "Use of $function was deprecated in $component $version.", 2 ); + } else { + wfWarn( "Use of $function is deprecated.", 2 ); + } + } +} + +/** + * Send a warning either to the debug log or in a PHP error depending on + * $wgDevelopmentWarnings + * + * @param $msg String: message to send + * @param $callerOffset Integer: number of items to go back in the backtrace to + * find the correct caller (1 = function calling wfWarn, ...) + * @param $level Integer: PHP error level; only used when $wgDevelopmentWarnings + * is true + */ +function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) { + global $wgDevelopmentWarnings; + + MWDebug::warning( $msg, $callerOffset + 2 ); + + $callers = wfDebugBacktrace(); + if ( isset( $callers[$callerOffset + 1] ) ) { + $callerfunc = $callers[$callerOffset + 1]; + $callerfile = $callers[$callerOffset]; + if ( isset( $callerfile['file'] ) && isset( $callerfile['line'] ) ) { + $file = $callerfile['file'] . ' at line ' . $callerfile['line']; + } else { + $file = '(internal function)'; + } + $func = ''; + if ( isset( $callerfunc['class'] ) ) { + $func .= $callerfunc['class'] . '::'; + } + if ( isset( $callerfunc['function'] ) ) { + $func .= $callerfunc['function']; + } + $msg .= " [Called from $func in $file]"; + } + + if ( $wgDevelopmentWarnings ) { + trigger_error( $msg, $level ); + } else { + wfDebug( "$msg\n" ); + } +} + /** * Log to a file without getting "file size exceeded" signals. * @@ -855,21 +1094,22 @@ function wfErrorLog( $text, $file ) { $text = preg_replace( '/^/m', $prefix . ' ', $text ); // Limit to 64KB - if ( strlen( $text ) > 65534 ) { - $text = substr( $text, 0, 65534 ); + if ( strlen( $text ) > 65506 ) { + $text = substr( $text, 0, 65506 ); } if ( substr( $text, -1 ) != "\n" ) { $text .= "\n"; } - } elseif ( strlen( $text ) > 65535 ) { - $text = substr( $text, 0, 65535 ); + } elseif ( strlen( $text ) > 65507 ) { + $text = substr( $text, 0, 65507 ); } $sock = socket_create( $domain, SOCK_DGRAM, SOL_UDP ); if ( !$sock ) { return; } + socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port ); socket_close( $sock ); } else { @@ -899,8 +1139,7 @@ function wfLogProfilingData() { // Get total page request time and only show pages that longer than // $wgProfileLimit time (default is 0) - $now = wfTime(); - $elapsed = $now - $wgRequestTime; + $elapsed = microtime( true ) - $wgRequestTime; if ( $elapsed <= $wgProfileLimit ) { return; } @@ -962,6 +1201,9 @@ function wfReadOnly() { return (bool)$wgReadOnly; } +/** + * @return bool + */ function wfReadOnlyReason() { global $wgReadOnly; wfReadOnly(); @@ -977,9 +1219,10 @@ function wfReadOnlyReason() { * a valid code create a language for that language, if * it is a string but not a valid code then make a basic * language object - * - a boolean: if it's false then use the current users - * language (as a fallback for the old parameter - * functionality), or if it is true then use the wikis + * - a boolean: if it's false then use the global object for + * the current user's language (as a fallback for the old parameter + * functionality), or if it is true then use global object + * for the wiki's content language. * @return Language object */ function wfGetLangObj( $langcode = false ) { @@ -1023,6 +1266,7 @@ function wfGetLangObj( $langcode = false ) { * @return Language */ function wfUILang() { + wfDeprecated( __METHOD__, '1.18' ); global $wgLang; return $wgLang; } @@ -1249,7 +1493,8 @@ function wfMsgWikiHtml( $key ) { $args = func_get_args(); array_shift( $args ); return wfMsgReplaceArgs( - MessageCache::singleton()->parse( wfMsgGetKey( $key ), null, /* can't be set to false */ true )->getText(), + MessageCache::singleton()->parse( wfMsgGetKey( $key ), null, + /* can't be set to false */ true, /* interface */ true )->getText(), $args ); } @@ -1311,13 +1556,18 @@ function wfMsgExt( $key, $options ) { } $messageCache = MessageCache::singleton(); - if( in_array( 'parse', $options, true ) ) { - $string = $messageCache->parse( $string, null, true, !$forContent, $langCodeObj )->getText(); - } elseif ( in_array( 'parseinline', $options, true ) ) { - $string = $messageCache->parse( $string, null, true, !$forContent, $langCodeObj )->getText(); - $m = array(); - if( preg_match( '/^

(.*)\n?<\/p>\n?$/sU', $string, $m ) ) { - $string = $m[1]; + $parseInline = in_array( 'parseinline', $options, true ); + if( in_array( 'parse', $options, true ) || $parseInline ) { + $string = $messageCache->parse( $string, null, true, !$forContent, $langCodeObj ); + if ( $string instanceof ParserOutput ) { + $string = $string->getText(); + } + + if ( $parseInline ) { + $m = array(); + if( preg_match( '/^

(.*)\n?<\/p>\n?$/sU', $string, $m ) ) { + $string = $m[1]; + } } } elseif ( in_array( 'parsemag', $options, true ) ) { $string = $messageCache->transform( $string, @@ -1353,7 +1603,7 @@ function wfEmptyMsg( $key ) { * Throw a debugging exception. This function previously once exited the process, * but now throws an exception instead, with similar results. * - * @param $msg String: message shown when dieing. + * @param $msg String: message shown when dying. */ function wfDebugDieBacktrace( $msg = '' ) { throw new MWException( $msg ); @@ -1397,8 +1647,7 @@ function wfHostname() { function wfReportTime() { global $wgRequestTime, $wgShowHostnames; - $now = wfTime(); - $elapsed = $now - $wgRequestTime; + $elapsed = microtime( true ) - $wgRequestTime; return $wgShowHostnames ? sprintf( '', wfHostname(), $elapsed ) @@ -1575,80 +1824,40 @@ function wfShowingResults( $offset, $limit ) { * @param $query String: optional URL query parameter string * @param $atend Bool: optional param for specified if this is the last page * @return String + * @deprecated in 1.19; use Language::viewPrevNext() instead */ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) { + wfDeprecated( __METHOD__, '1.19' ); + global $wgLang; - $fmtLimit = $wgLang->formatNum( $limit ); - // @todo FIXME: Why on earth this needs one message for the text and another one for tooltip? - # Get prev/next link display text - $prev = wfMsgExt( 'prevn', array( 'parsemag', 'escape' ), $fmtLimit ); - $next = wfMsgExt( 'nextn', array( 'parsemag', 'escape' ), $fmtLimit ); - # Get prev/next link title text - $pTitle = wfMsgExt( 'prevn-title', array( 'parsemag', 'escape' ), $fmtLimit ); - $nTitle = wfMsgExt( 'nextn-title', array( 'parsemag', 'escape' ), $fmtLimit ); - # Fetch the title object + + $query = wfCgiToArray( $query ); + if( is_object( $link ) ) { - $title =& $link; + $title = $link; } else { $title = Title::newFromText( $link ); if( is_null( $title ) ) { return false; } } - # Make 'previous' link - if( 0 != $offset ) { - $po = $offset - $limit; - $po = max( $po, 0 ); - $q = "limit={$limit}&offset={$po}"; - if( $query != '' ) { - $q .= '&' . $query; - } - $plink = '{$prev}"; - } else { - $plink = $prev; - } - # Make 'next' link - $no = $offset + $limit; - $q = "limit={$limit}&offset={$no}"; - if( $query != '' ) { - $q .= '&' . $query; - } - if( $atend ) { - $nlink = $next; - } else { - $nlink = '{$next}"; - } - # Make links to set number of items per page - $nums = $wgLang->pipeList( array( - 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 wfMsgHtml( 'viewprevnext', $plink, $nlink, $nums ); + + return $wgLang->viewPrevNext( $title, $offset, $limit, $query, $atend ); } /** - * Generate links for (20|50|100...) items-per-page links + * Make a list item, used by various special pages * - * @param $offset String - * @param $limit Integer - * @param $title Title - * @param $query String: optional URL query parameter string + * @param $page String Page link + * @param $details String Text between brackets + * @param $oppositedm Boolean Add the direction mark opposite to your + * language, to display text properly + * @return String + * @deprecated since 1.19; use Language::specialList() instead */ -function wfNumLink( $offset, $limit, $title, $query = '' ) { +function wfSpecialList( $page, $details, $oppositedm = true ) { global $wgLang; - if( $query == '' ) { - $q = ''; - } else { - $q = $query.'&'; - } - $q .= "limit={$limit}&offset={$offset}"; - $fmtLimit = $wgLang->formatNum( $limit ); - $lTitle = wfMsgExt( 'shown-title', array( 'parsemag', 'escape' ), $limit ); - $s = '{$fmtLimit}"; - return $s; + return $wgLang->specialList( $page, $details, $oppositedm ); } /** @@ -1675,7 +1884,7 @@ function wfClientAcceptsGzip( $force = false ) { $result = false; return $result; } - wfDebug( " accepts gzip\n" ); + wfDebug( "wfClientAcceptsGzip: client accepts gzip.\n" ); $result = true; } } @@ -1750,6 +1959,8 @@ function wfSetVar( &$dest, $source, $force = false ) { * @param $dest Int * @param $bit Int * @param $state Bool + * + * @return bool */ function wfSetBit( &$dest, $bit, $state = true ) { $temp = (bool)( $dest & $bit ); @@ -1764,248 +1975,37 @@ function wfSetBit( &$dest, $bit, $state = true ) { } /** - * 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. - * - * Also fixes the locale problems on Linux in PHP 5.2.6+ (bug backported to - * earlier distro releases of PHP) + * A wrapper around the PHP function var_export(). + * Either print it or add it to the regular output ($wgOut). * - * @param varargs - * @return String + * @param $var A PHP variable to dump. */ -function wfEscapeShellArg( ) { - wfInitShellLocale(); - - $args = func_get_args(); - $first = true; - $retVal = ''; - foreach ( $args as $arg ) { - if ( !$first ) { - $retVal .= ' '; - } else { - $first = false; - } - - if ( wfIsWindows() ) { - // Escaping for an MSVC-style command line parser and CMD.EXE - // Refs: - // * http://web.archive.org/web/20020708081031/http://mailman.lyra.org/pipermail/scite-interest/2002-March/000436.html - // * http://technet.microsoft.com/en-us/library/cc723564.aspx - // * Bug #13518 - // * CR r63214 - // Double the backslashes before any double quotes. Escape the double quotes. - $tokens = preg_split( '/(\\\\*")/', $arg, -1, PREG_SPLIT_DELIM_CAPTURE ); - $arg = ''; - $iteration = 0; - foreach ( $tokens as $token ) { - if ( $iteration % 2 == 1 ) { - // Delimiter, a double quote preceded by zero or more slashes - $arg .= str_replace( '\\', '\\\\', substr( $token, 0, -1 ) ) . '\\"'; - } elseif ( $iteration % 4 == 2 ) { - // ^ in $token will be outside quotes, need to be escaped - $arg .= str_replace( '^', '^^', $token ); - } else { // $iteration % 4 == 0 - // ^ in $token will appear inside double quotes, so leave as is - $arg .= $token; - } - $iteration++; - } - // Double the backslashes before the end of the string, because - // we will soon add a quote - $m = array(); - if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) { - $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] ); - } - - // Add surrounding quotes - $retVal .= '"' . $arg . '"'; - } else { - $retVal .= escapeshellarg( $arg ); - } +function wfVarDump( $var ) { + global $wgOut; + $s = str_replace( "\n", "
\n", var_export( $var, true ) . "\n" ); + if ( headers_sent() || !isset( $wgOut ) || !is_object( $wgOut ) ) { + print $s; + } else { + $wgOut->addHTML( $s ); } - return $retVal; } /** - * wfMerge attempts to merge differences between three texts. - * Returns true for a clean merge and false for failure or a conflict. + * Provide a simple HTTP error. * - * @param $old String - * @param $mine String - * @param $yours String - * @param $result String - * @return Bool + * @param $code Int|String + * @param $label String + * @param $desc String */ -function wfMerge( $old, $mine, $yours, &$result ) { - global $wgDiff3; - - # This check may also protect against code injection in - # case of broken installations. - wfSuppressWarnings(); - $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 ); - wfRestoreWarnings(); - - if( !$haveDiff3 ) { - wfDebug( "diff3 not found\n" ); - return false; - } - - # Make temporary files - $td = wfTempDir(); - $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( $yourtextFile, $yours ); - fclose( $yourtextFile ); - - # Check for a conflict - $cmd = $wgDiff3 . ' -a --overlap-only ' . - wfEscapeShellArg( $mytextName ) . ' ' . - wfEscapeShellArg( $oldtextName ) . ' ' . - wfEscapeShellArg( $yourtextName ); - $handle = popen( $cmd, 'r' ); - - if( fgets( $handle, 1024 ) ) { - $conflict = true; - } else { - $conflict = false; - } - pclose( $handle ); - - # Merge differences - $cmd = $wgDiff3 . ' -a -e --merge ' . - wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName ); - $handle = popen( $cmd, 'r' ); - $result = ''; - do { - $data = fread( $handle, 8192 ); - if ( strlen( $data ) == 0 ) { - break; - } - $result .= $data; - } while ( true ); - pclose( $handle ); - unlink( $mytextName ); - unlink( $oldtextName ); - unlink( $yourtextName ); - - if ( $result === '' && $old !== '' && !$conflict ) { - wfDebug( "Unexpected null result from diff3. Command: $cmd\n" ); - $conflict = true; - } - return !$conflict; -} - -/** - * Returns unified plain-text diff of two texts. - * Useful for machine processing of diffs. - * - * @param $before String: the text before the changes. - * @param $after String: the text after the changes. - * @param $params String: command-line options for the diff command. - * @return String: unified diff of $before and $after - */ -function wfDiff( $before, $after, $params = '-u' ) { - if ( $before == $after ) { - return ''; - } - - global $wgDiff; - wfSuppressWarnings(); - $haveDiff = $wgDiff && file_exists( $wgDiff ); - wfRestoreWarnings(); - - # This check may also protect against code injection in - # case of broken installations. - if( !$haveDiff ) { - wfDebug( "diff executable not found\n" ); - $diffs = new Diff( explode( "\n", $before ), explode( "\n", $after ) ); - $format = new UnifiedDiffFormatter(); - return $format->format( $diffs ); - } - - # Make temporary files - $td = wfTempDir(); - $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' ); - $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' ); - - fwrite( $oldtextFile, $before ); - fclose( $oldtextFile ); - fwrite( $newtextFile, $after ); - fclose( $newtextFile ); - - // Get the diff of the two files - $cmd = "$wgDiff " . $params . ' ' . wfEscapeShellArg( $oldtextName, $newtextName ); - - $h = popen( $cmd, 'r' ); - - $diff = ''; - - do { - $data = fread( $h, 8192 ); - if ( strlen( $data ) == 0 ) { - break; - } - $diff .= $data; - } while ( true ); - - // Clean up - pclose( $h ); - unlink( $oldtextName ); - unlink( $newtextName ); - - // Kill the --- and +++ lines. They're not useful. - $diff_lines = explode( "\n", $diff ); - if ( strpos( $diff_lines[0], '---' ) === 0 ) { - unset( $diff_lines[0] ); - } - if ( strpos( $diff_lines[1], '+++' ) === 0 ) { - unset( $diff_lines[1] ); - } - - $diff = implode( "\n", $diff_lines ); - - return $diff; -} - -/** - * A wrapper around the PHP function var_export(). - * Either print it or add it to the regular output ($wgOut). - * - * @param $var A PHP variable to dump. - */ -function wfVarDump( $var ) { - global $wgOut; - $s = str_replace( "\n", "
\n", var_export( $var, true ) . "\n" ); - if ( headers_sent() || !isset( $wgOut ) || !is_object( $wgOut ) ) { - print $s; - } else { - $wgOut->addHTML( $s ); - } -} - -/** - * Provide a simple HTTP error. - * - * @param $code Int|String - * @param $label String - * @param $desc String - */ -function wfHttpError( $code, $label, $desc ) { - global $wgOut; - $wgOut->disable(); - header( "HTTP/1.0 $code $label" ); - header( "Status: $code $label" ); - $wgOut->sendCacheControl(); +function wfHttpError( $code, $label, $desc ) { + global $wgOut; + $wgOut->disable(); + header( "HTTP/1.0 $code $label" ); + header( "Status: $code $label" ); + $wgOut->sendCacheControl(); header( 'Content-type: text/html; charset=utf-8' ); - print "". + print "" . '' . htmlspecialchars( $label ) . '

' . @@ -2161,7 +2161,7 @@ function mimeTypeMatch( $type, $avail ) { function wfNegotiateType( $cprefs, $sprefs ) { $combine = array(); - foreach( array_keys($sprefs) as $type ) { + foreach( array_keys( $sprefs ) as $type ) { $parts = explode( '/', $type ); if( $parts[1] != '*' ) { $ckey = mimeTypeMatch( $type, $cprefs ); @@ -2213,7 +2213,7 @@ function wfSuppressWarnings( $end = false ) { } else { if ( !$suppressCount ) { // E_DEPRECATED is undefined in PHP 5.2 - if( !defined( 'E_DEPRECATED' ) ){ + if( !defined( 'E_DEPRECATED' ) ) { define( 'E_DEPRECATED', 8192 ); } $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED ) ); @@ -2313,7 +2313,7 @@ function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) { } elseif ( preg_match( '/^-?\d{1,13}$/D', $ts ) ) { # TS_UNIX $uts = $ts; - $strtime = "@$ts"; // Undocumented? + $strtime = "@$ts"; // http://php.net/manual/en/datetime.formats.compound.php } elseif ( preg_match( '/^\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}.\d{6}$/', $ts ) ) { # TS_ORACLE // session altered to DD-MM-YYYY HH24:MI:SS.FF6 $strtime = preg_replace( '/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3", @@ -2326,7 +2326,7 @@ function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) { # TS_POSTGRES } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d* GMT$/', $ts, $da ) ) { # TS_POSTGRES - } elseif (preg_match('/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.\d\d\d$/',$ts,$da)) { + } elseif (preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.\d\d\d$/', $ts, $da ) ) { # TS_DB2 } elseif ( preg_match( '/^[ \t\r\n]*([A-Z][a-z]{2},[ \t\r\n]*)?' . # Day of week '\d\d?[ \t\r\n]*[A-Z][a-z]{2}[ \t\r\n]*\d{2}(?:\d{2})?' . # dd Mon yyyy @@ -2508,8 +2508,12 @@ function wfTempDir() { function wfMkdirParents( $dir, $mode = null, $caller = null ) { global $wgDirectoryMode; + if ( FileBackend::isStoragePath( $dir ) ) { // sanity + throw new MWException( __FUNCTION__ . " given storage path `$dir`."); + } + if ( !is_null( $caller ) ) { - wfDebug( "$caller: called wfMkdirParents($dir)" ); + wfDebug( "$caller: called wfMkdirParents($dir)\n" ); } if( strval( $dir ) === '' || file_exists( $dir ) ) { @@ -2585,6 +2589,29 @@ function wfIncrStats( $key, $count = 1 ) { } } +/** + * Remove a directory and all its content. + * Does not hide error. + */ +function wfRecursiveRemoveDir( $dir ) { + wfDebug( __FUNCTION__ . "( $dir )\n" ); + // taken from http://de3.php.net/manual/en/function.rmdir.php#98622 + if ( is_dir( $dir ) ) { + $objects = scandir( $dir ); + foreach ( $objects as $object ) { + if ( $object != "." && $object != ".." ) { + if ( filetype( $dir . '/' . $object ) == "dir" ) { + wfRecursiveRemoveDir( $dir . '/' . $object ); + } else { + unlink( $dir . '/' . $object ); + } + } + } + reset( $objects ); + rmdir( $dir ); + } +} + /** * @param $nr Mixed: the number to format * @param $acc Integer: the number of digits after the decimal point, default 2 @@ -2611,23 +2638,6 @@ function in_string( $needle, $str, $insensitive = false ) { return $func( $str, $needle ) !== false; } -/** - * Make a list item, used by various special pages - * - * @param $page String Page link - * @param $details String Text between brackets - * @param $oppositedm Boolean Add the direction mark opposite to your - * language, to display text properly - * @return String - */ -function wfSpecialList( $page, $details, $oppositedm = true ) { - global $wgLang; - $dirmark = ( $oppositedm ? $wgLang->getDirMark( true ) : '' ) . - $wgLang->getDirMark(); - $details = $details ? $dirmark . " ($details)" : ''; - return $page . $details; -} - /** * Safety wrapper around ini_get() for boolean settings. * The values returned from ini_get() are pre-normalized for settings @@ -2695,6 +2705,70 @@ function wfDl( $extension, $fileName = null ) { return extension_loaded( $extension ); } +/** + * 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. + * + * Also fixes the locale problems on Linux in PHP 5.2.6+ (bug backported to + * earlier distro releases of PHP) + * + * @param varargs + * @return String + */ +function wfEscapeShellArg( ) { + wfInitShellLocale(); + + $args = func_get_args(); + $first = true; + $retVal = ''; + foreach ( $args as $arg ) { + if ( !$first ) { + $retVal .= ' '; + } else { + $first = false; + } + + if ( wfIsWindows() ) { + // Escaping for an MSVC-style command line parser and CMD.EXE + // Refs: + // * http://web.archive.org/web/20020708081031/http://mailman.lyra.org/pipermail/scite-interest/2002-March/000436.html + // * http://technet.microsoft.com/en-us/library/cc723564.aspx + // * Bug #13518 + // * CR r63214 + // Double the backslashes before any double quotes. Escape the double quotes. + $tokens = preg_split( '/(\\\\*")/', $arg, -1, PREG_SPLIT_DELIM_CAPTURE ); + $arg = ''; + $iteration = 0; + foreach ( $tokens as $token ) { + if ( $iteration % 2 == 1 ) { + // Delimiter, a double quote preceded by zero or more slashes + $arg .= str_replace( '\\', '\\\\', substr( $token, 0, -1 ) ) . '\\"'; + } elseif ( $iteration % 4 == 2 ) { + // ^ in $token will be outside quotes, need to be escaped + $arg .= str_replace( '^', '^^', $token ); + } else { // $iteration % 4 == 0 + // ^ in $token will appear inside double quotes, so leave as is + $arg .= $token; + } + $iteration++; + } + // Double the backslashes before the end of the string, because + // we will soon add a quote + $m = array(); + if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) { + $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] ); + } + + // Add surrounding quotes + $retVal .= '"' . $arg . '"'; + } else { + $retVal .= escapeshellarg( $arg ); + } + } + return $retVal; +} + /** * Execute a shell command, with time and memory limits mirrored from the PHP * configuration if supported. @@ -2804,6 +2878,178 @@ function wfInitShellLocale() { } } +/** + * Generate a shell-escaped command line string to run a maintenance script. + * Note that $parameters should be a flat array and an option with an argument + * should consist of two consecutive items in the array (do not use "--option value"). + * @param $script string MediaWiki maintenance script path + * @param $parameters Array Arguments and options to the script + * @param $options Array Associative array of options: + * 'php': The path to the php executable + * 'wrapper': Path to a PHP wrapper to handle the maintenance script + * @return Array + */ +function wfShellMaintenanceCmd( $script, array $parameters = array(), array $options = array() ) { + global $wgPhpCli; + // Give site config file a chance to run the script in a wrapper. + // The caller may likely want to call wfBasename() on $script. + wfRunHooks( 'wfShellMaintenanceCmd', array( &$script, &$parameters, &$options ) ); + $cmd = isset( $options['php'] ) ? array( $options['php'] ) : array( $wgPhpCli ); + if ( isset( $options['wrapper'] ) ) { + $cmd[] = $options['wrapper']; + } + $cmd[] = $script; + // Escape each parameter for shell + return implode( " ", array_map( 'wfEscapeShellArg', array_merge( $cmd, $parameters ) ) ); +} + +/** + * wfMerge attempts to merge differences between three texts. + * Returns true for a clean merge and false for failure or a conflict. + * + * @param $old String + * @param $mine String + * @param $yours String + * @param $result String + * @return Bool + */ +function wfMerge( $old, $mine, $yours, &$result ) { + global $wgDiff3; + + # This check may also protect against code injection in + # case of broken installations. + wfSuppressWarnings(); + $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 ); + wfRestoreWarnings(); + + if( !$haveDiff3 ) { + wfDebug( "diff3 not found\n" ); + return false; + } + + # Make temporary files + $td = wfTempDir(); + $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( $yourtextFile, $yours ); + fclose( $yourtextFile ); + + # Check for a conflict + $cmd = $wgDiff3 . ' -a --overlap-only ' . + wfEscapeShellArg( $mytextName ) . ' ' . + wfEscapeShellArg( $oldtextName ) . ' ' . + wfEscapeShellArg( $yourtextName ); + $handle = popen( $cmd, 'r' ); + + if( fgets( $handle, 1024 ) ) { + $conflict = true; + } else { + $conflict = false; + } + pclose( $handle ); + + # Merge differences + $cmd = $wgDiff3 . ' -a -e --merge ' . + wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName ); + $handle = popen( $cmd, 'r' ); + $result = ''; + do { + $data = fread( $handle, 8192 ); + if ( strlen( $data ) == 0 ) { + break; + } + $result .= $data; + } while ( true ); + pclose( $handle ); + unlink( $mytextName ); + unlink( $oldtextName ); + unlink( $yourtextName ); + + if ( $result === '' && $old !== '' && !$conflict ) { + wfDebug( "Unexpected null result from diff3. Command: $cmd\n" ); + $conflict = true; + } + return !$conflict; +} + +/** + * Returns unified plain-text diff of two texts. + * Useful for machine processing of diffs. + * + * @param $before String: the text before the changes. + * @param $after String: the text after the changes. + * @param $params String: command-line options for the diff command. + * @return String: unified diff of $before and $after + */ +function wfDiff( $before, $after, $params = '-u' ) { + if ( $before == $after ) { + return ''; + } + + global $wgDiff; + wfSuppressWarnings(); + $haveDiff = $wgDiff && file_exists( $wgDiff ); + wfRestoreWarnings(); + + # This check may also protect against code injection in + # case of broken installations. + if( !$haveDiff ) { + wfDebug( "diff executable not found\n" ); + $diffs = new Diff( explode( "\n", $before ), explode( "\n", $after ) ); + $format = new UnifiedDiffFormatter(); + return $format->format( $diffs ); + } + + # Make temporary files + $td = wfTempDir(); + $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' ); + $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' ); + + fwrite( $oldtextFile, $before ); + fclose( $oldtextFile ); + fwrite( $newtextFile, $after ); + fclose( $newtextFile ); + + // Get the diff of the two files + $cmd = "$wgDiff " . $params . ' ' . wfEscapeShellArg( $oldtextName, $newtextName ); + + $h = popen( $cmd, 'r' ); + + $diff = ''; + + do { + $data = fread( $h, 8192 ); + if ( strlen( $data ) == 0 ) { + break; + } + $diff .= $data; + } while ( true ); + + // Clean up + pclose( $h ); + unlink( $oldtextName ); + unlink( $newtextName ); + + // Kill the --- and +++ lines. They're not useful. + $diff_lines = explode( "\n", $diff ); + if ( strpos( $diff_lines[0], '---' ) === 0 ) { + unset( $diff_lines[0] ); + } + if ( strpos( $diff_lines[1], '+++' ) === 0 ) { + unset( $diff_lines[1] ); + } + + $diff = implode( "\n", $diff_lines ); + + return $diff; +} + /** * This function works like "use VERSION" in Perl, the program will die with a * backtrace if the current version of PHP is less than the version provided @@ -2920,35 +3166,13 @@ function wfRelativePath( $path, $from ) { /** * Do any deferred updates and clear the list * - * @param $commit String: set to 'commit' to commit after every update to - * prevent lock contention + * @deprecated since 1.19 + * @see DeferredUpdates::doUpdate() + * @param $commit string */ function wfDoUpdates( $commit = '' ) { - global $wgDeferredUpdateList; - - wfProfileIn( __METHOD__ ); - - // No need to get master connections in case of empty updates array - if ( !count( $wgDeferredUpdateList ) ) { - wfProfileOut( __METHOD__ ); - return; - } - - $doCommit = $commit == 'commit'; - if ( $doCommit ) { - $dbw = wfGetDB( DB_MASTER ); - } - - foreach ( $wgDeferredUpdateList as $update ) { - $update->doUpdate(); - - if ( $doCommit && $dbw->trxLevel() ) { - $dbw->commit(); - } - } - - $wgDeferredUpdateList = array(); - wfProfileOut( __METHOD__ ); + wfDeprecated( __METHOD__, '1.19' ); + DeferredUpdates::doUpdates( $commit ); } /** @@ -3043,13 +3267,17 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = t * * @param $name String * @param $p Array: parameters + * @return object * @deprecated since 1.18, warnings in 1.18, removal in 1.20 */ function wfCreateObject( $name, $p ) { - wfDeprecated( __FUNCTION__ ); + wfDeprecated( __FUNCTION__, '1.18' ); return MWFunction::newObj( $name, $p ); } +/** + * @return bool + */ function wfHttpOnlySafe() { global $wgHttpOnlyBlacklist; @@ -3164,8 +3392,10 @@ function wfGetPrecompiledData( $name ) { * @return String */ function wfMemcKey( /*... */ ) { + global $wgCachePrefix; + $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix; $args = func_get_args(); - $key = wfWikiID() . ':' . implode( ':', $args ); + $key = $prefix . ':' . implode( ':', $args ); $key = str_replace( ' ', '_', $key ); return $key; } @@ -3207,7 +3437,8 @@ function wfWikiID() { * Split a wiki ID into DB name and table prefix * * @param $wiki String - * @param $bits String + * + * @return array */ function wfSplitWikiID( $wiki ) { $bits = explode( '-', $wiki, 2 ); @@ -3290,13 +3521,22 @@ function wfFindFile( $title, $options = array() ) { * Get an object referring to a locally registered file. * Returns a valid placeholder object if the file does not exist. * - * @param $title Title or String - * @return File, or null if passed an invalid Title + * @param $title Title|String + * @return File|null A File, or null if passed an invalid Title */ function wfLocalFile( $title ) { return RepoGroup::singleton()->getLocalRepo()->newFile( $title ); } +/** + * Stream a file to the browser. Back-compat alias for StreamFile::stream() + * @deprecated since 1.19 + */ +function wfStreamFile( $fname, $headers = array() ) { + wfDeprecated( __FUNCTION__, '1.19' ); + StreamFile::stream( $fname, $headers ); +} + /** * Should low-performance queries be disabled? * @@ -3364,7 +3604,7 @@ function wfBoolToStr( $value ) { * @codeCoverageIgnore */ function wfLoadExtensionMessages() { - wfDeprecated( __FUNCTION__ ); + wfDeprecated( __FUNCTION__, '1.16' ); } /** @@ -3378,59 +3618,6 @@ function wfGetNull() { : '/dev/null'; } -/** - * Throws a warning that $function is deprecated - * - * @param $function String - * @return null - */ -function wfDeprecated( $function ) { - static $functionsWarned = array(); - if ( !isset( $functionsWarned[$function] ) ) { - $functionsWarned[$function] = true; - wfWarn( "Use of $function is deprecated.", 2 ); - } -} - -/** - * Send a warning either to the debug log or in a PHP error depending on - * $wgDevelopmentWarnings - * - * @param $msg String: message to send - * @param $callerOffset Integer: number of items to go back in the backtrace to - * find the correct caller (1 = function calling wfWarn, ...) - * @param $level Integer: PHP error level; only used when $wgDevelopmentWarnings - * is true - */ -function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) { - global $wgDevelopmentWarnings; - - $callers = wfDebugBacktrace(); - if ( isset( $callers[$callerOffset + 1] ) ) { - $callerfunc = $callers[$callerOffset + 1]; - $callerfile = $callers[$callerOffset]; - if ( isset( $callerfile['file'] ) && isset( $callerfile['line'] ) ) { - $file = $callerfile['file'] . ' at line ' . $callerfile['line']; - } else { - $file = '(internal function)'; - } - $func = ''; - if ( isset( $callerfunc['class'] ) ) { - $func .= $callerfunc['class'] . '::'; - } - if ( isset( $callerfunc['function'] ) ) { - $func .= $callerfunc['function']; - } - $msg .= " [Called from $func in $file]"; - } - - if ( $wgDevelopmentWarnings ) { - trigger_error( $msg, $level ); - } else { - wfDebug( "$msg\n" ); - } -} - /** * Modern version of wfWaitForSlaves(). Instead of looking at replication lag * and waiting for it to go down, this waits for the slaves to catch up to the @@ -3440,7 +3627,6 @@ function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) { * * @param $maxLag Integer (deprecated) * @param $wiki mixed Wiki identifier accepted by wfGetLB - * @return null */ function wfWaitForSlaves( $maxLag = false, $wiki = false ) { $lb = wfGetLB( $wiki ); @@ -3458,7 +3644,7 @@ function wfWaitForSlaves( $maxLag = false, $wiki = false ) { * @deprecated since 1.18, warnings in 1.18, remove in 1.20 */ function wfOut( $s ) { - wfDeprecated( __METHOD__ ); + wfDeprecated( __FUNCTION__, '1.18' ); global $wgCommandLineMode; if ( $wgCommandLineMode ) { echo $s; @@ -3472,6 +3658,7 @@ function wfOut( $s ) { * Count down from $n to zero on the terminal, with a one-second pause * between showing each number. For use in command-line scripts. * @codeCoverageIgnore + * @param $n int */ function wfCountDown( $n ) { for ( $i = $n; $i >= 0; $i-- ) { @@ -3580,7 +3767,7 @@ function wfShorthandToInteger( $string = '' ) { * See unit test for examples. * * @param $code String: The language code. - * @return $langCode String: The language code which complying with BCP 47 standards. + * @return String: The language code which complying with BCP 47 standards. */ function wfBCP47( $code ) { $codeSegment = explode( '-', $code ); @@ -3588,7 +3775,7 @@ function wfBCP47( $code ) { foreach ( $codeSegment as $segNo => $seg ) { if ( count( $codeSegment ) > 0 ) { // when previous segment is x, it is a private segment and should be lc - if( $segNo > 0 && strtolower( $codeSegment[($segNo - 1)] ) == 'x') { + if( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) { $codeBCP[$segNo] = strtolower( $seg ); // ISO 3166 country code } elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) { @@ -3654,7 +3841,7 @@ function wfGetParserCacheStorage() { * * @param $event String: event name * @param $args Array: parameters passed to hook functions - * @return Boolean + * @return Boolean True if no handler aborted the hook */ function wfRunHooks( $event, $args = array() ) { return Hooks::run( $event, $args ); -- cgit v1.2.3-54-g00ecf