2004-04-04 11:26:29 +00:00
|
|
|
|
<?php
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
|
* @defgroup Language Language
|
|
|
|
|
|
*
|
|
|
|
|
|
* @file
|
|
|
|
|
|
* @ingroup Language
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if( !defined( 'MEDIAWIKI' ) ) {
|
|
|
|
|
|
echo "This file is part of MediaWiki, it is not a valid entry point.\n";
|
|
|
|
|
|
exit( 1 );
|
|
|
|
|
|
}
|
2004-08-06 21:19:24 +00:00
|
|
|
|
|
2004-06-11 04:50:29 +00:00
|
|
|
|
# Read language names
|
2007-09-11 15:22:53 +00:00
|
|
|
|
global $wgLanguageNames;
|
Prevent some unnecessary lstat system calls, generated by include or require directives.
This can be done either by:
* Using explicit full paths, using the $IP global for the installation directory full path, and then working down the tree from there.
* Using explicit full paths, using the "dirname(__FILE__)" directive to get a full directory path for the includer file.
* Occasionally removing the line altogether, and then for some files the inclusion is handled by the autoloader.
For example, if the "extensions/wikihiero/wh_main.php" file does an include or require on "wh_list.php", then PHP does the following:
* tries to open "wiki/wh_list.php", and fails.
* tries to open "wiki/includes/wh_list.php", and fails.
* tries to open "wiki/languages/wh_list.php", and fails.
* tries to open "wiki/extensions/wikihiero/wh_list.php", and succeeds.
So in this example, the first 3 calls can be prevented if PHP is told where the file is.
Testing Method: On a Linux box, run these commands to attach strace to all the apache2 processes, and log their system calls to a temporary file, then generate some activity, and then stop the strace:
-----------------------------------
rm /tmp/strace-log.txt
strace -tt -o /tmp/strace-log.txt -p `pidof apache2 | sed 's/ / -p /g'` &
php maintenance/fuzz-tester.php --keep-passed-tests --include-binary --max-runtime=3 > /tmp/strace-tests.txt
killall -9 strace
grep "No such file or directory" /tmp/strace-log.txt | sort -u
-----------------------------------
Any failed file stats will be marked with: "-1 ENOENT (No such file or directory)".
Also:
* Strict Standards: Undefined offset: 230 in includes/normal/UtfNormal.php on line 637
* Strict Standards: iconv() [<a href='function.iconv'>function.iconv</a>]: Detected an illegal character in input string in languages/Language.php on line 776
[Note: Partial only - despite adding "//IGNORE", it still seems to be possible with some
messed- up binary input to cause PHP 5.1.2's iconv() function to squeal like a stuck pig].
* Update one $fname variable (method belongs to HistoryBlobStub class).
2007-02-09 05:36:56 +00:00
|
|
|
|
require_once( dirname(__FILE__) . '/Names.php' ) ;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
global $wgInputEncoding, $wgOutputEncoding;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* These are always UTF-8, they exist only for backwards compatibility
|
|
|
|
|
|
*/
|
|
|
|
|
|
$wgInputEncoding = "UTF-8";
|
|
|
|
|
|
$wgOutputEncoding = "UTF-8";
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if( function_exists( 'mb_strtoupper' ) ) {
|
|
|
|
|
|
mb_internal_encoding('UTF-8');
|
2006-01-22 00:49:58 +00:00
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* a fake language converter
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup Language
|
|
|
|
|
|
*/
|
2006-07-26 07:15:39 +00:00
|
|
|
|
class FakeConverter {
|
2006-05-11 22:40:38 +00:00
|
|
|
|
var $mLang;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function FakeConverter($langobj) {$this->mLang = $langobj;}
|
2005-04-15 14:12:39 +00:00
|
|
|
|
function convert($t, $i) {return $t;}
|
2006-03-01 01:57:53 +00:00
|
|
|
|
function parserConvert($t, $p) {return $t;}
|
2005-07-06 07:53:51 +00:00
|
|
|
|
function getVariants() { return array( $this->mLang->getCode() ); }
|
|
|
|
|
|
function getPreferredVariant() {return $this->mLang->getCode(); }
|
2008-08-25 18:06:54 +00:00
|
|
|
|
function findVariantLink(&$l, &$n, $forTemplate = false) {}
|
2005-04-15 14:12:39 +00:00
|
|
|
|
function getExtraHashOptions() {return '';}
|
|
|
|
|
|
function getParsedTitle() {return '';}
|
2006-09-20 10:22:12 +00:00
|
|
|
|
function markNoConversion($text, $noParse=false) {return $text;}
|
2005-04-28 03:33:54 +00:00
|
|
|
|
function convertCategoryKey( $key ) {return $key; }
|
2006-09-20 10:22:12 +00:00
|
|
|
|
function convertLinkToAllVariants($text){ return array( $this->mLang->getCode() => $text); }
|
2006-12-11 23:33:27 +00:00
|
|
|
|
function armourMath($text){ return $text; }
|
2005-04-15 14:12:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Internationalisation code
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @ingroup Language
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
|
*/
|
2003-04-14 23:10:40 +00:00
|
|
|
|
class Language {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
var $mConverter, $mVariants, $mCode, $mLoaded = false;
|
2007-09-04 02:48:34 +00:00
|
|
|
|
var $mMagicExtensions = array(), $mMagicHookDone = false;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
2008-12-25 18:00:26 +00:00
|
|
|
|
static public $mLocalisationKeys = array(
|
|
|
|
|
|
'fallback', 'namespaceNames', 'mathNames', 'bookstoreList',
|
|
|
|
|
|
'magicWords', 'messages', 'rtl', 'digitTransformTable',
|
2006-07-26 07:15:39 +00:00
|
|
|
|
'separatorTransformTable', 'fallback8bitEncoding', 'linkPrefixExtension',
|
2008-07-04 10:34:41 +00:00
|
|
|
|
'defaultUserOptionOverrides', 'linkTrail', 'namespaceAliases',
|
|
|
|
|
|
'dateFormats', 'datePreferences', 'datePreferenceMigrationMap',
|
|
|
|
|
|
'defaultDateFormat', 'extraUserToggles', 'specialPageAliases',
|
|
|
|
|
|
'imageFiles'
|
|
|
|
|
|
);
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
2008-07-04 10:34:41 +00:00
|
|
|
|
static public $mMergeableMapKeys = array( 'messages', 'namespaceNames', 'mathNames',
|
|
|
|
|
|
'dateFormats', 'defaultUserOptionOverrides', 'magicWords', 'imageFiles' );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
|
|
|
|
|
static public $mMergeableListKeys = array( 'extraUserToggles' );
|
|
|
|
|
|
|
2006-10-30 06:25:31 +00:00
|
|
|
|
static public $mMergeableAliasListKeys = array( 'specialPageAliases' );
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
static public $mLocalisationCache = array();
|
2008-11-11 23:26:07 +00:00
|
|
|
|
static public $mLangObjCache = array();
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
|
|
|
|
|
static public $mWeekdayMsgs = array(
|
|
|
|
|
|
'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
|
|
|
|
|
|
'friday', 'saturday'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
static public $mWeekdayAbbrevMsgs = array(
|
|
|
|
|
|
'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
static public $mMonthMsgs = array(
|
|
|
|
|
|
'january', 'february', 'march', 'april', 'may_long', 'june',
|
|
|
|
|
|
'july', 'august', 'september', 'october', 'november',
|
|
|
|
|
|
'december'
|
|
|
|
|
|
);
|
|
|
|
|
|
static public $mMonthGenMsgs = array(
|
|
|
|
|
|
'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
|
|
|
|
|
|
'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen',
|
|
|
|
|
|
'december-gen'
|
|
|
|
|
|
);
|
|
|
|
|
|
static public $mMonthAbbrevMsgs = array(
|
|
|
|
|
|
'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
|
|
|
|
|
|
'sep', 'oct', 'nov', 'dec'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2007-11-13 04:05:13 +00:00
|
|
|
|
static public $mIranianCalendarMonthMsgs = array(
|
|
|
|
|
|
'iranian-calendar-m1', 'iranian-calendar-m2', 'iranian-calendar-m3',
|
|
|
|
|
|
'iranian-calendar-m4', 'iranian-calendar-m5', 'iranian-calendar-m6',
|
|
|
|
|
|
'iranian-calendar-m7', 'iranian-calendar-m8', 'iranian-calendar-m9',
|
|
|
|
|
|
'iranian-calendar-m10', 'iranian-calendar-m11', 'iranian-calendar-m12'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2007-11-13 17:17:07 +00:00
|
|
|
|
static public $mHebrewCalendarMonthMsgs = array(
|
|
|
|
|
|
'hebrew-calendar-m1', 'hebrew-calendar-m2', 'hebrew-calendar-m3',
|
|
|
|
|
|
'hebrew-calendar-m4', 'hebrew-calendar-m5', 'hebrew-calendar-m6',
|
|
|
|
|
|
'hebrew-calendar-m7', 'hebrew-calendar-m8', 'hebrew-calendar-m9',
|
|
|
|
|
|
'hebrew-calendar-m10', 'hebrew-calendar-m11', 'hebrew-calendar-m12',
|
|
|
|
|
|
'hebrew-calendar-m6a', 'hebrew-calendar-m6b'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
static public $mHebrewCalendarMonthGenMsgs = array(
|
|
|
|
|
|
'hebrew-calendar-m1-gen', 'hebrew-calendar-m2-gen', 'hebrew-calendar-m3-gen',
|
|
|
|
|
|
'hebrew-calendar-m4-gen', 'hebrew-calendar-m5-gen', 'hebrew-calendar-m6-gen',
|
|
|
|
|
|
'hebrew-calendar-m7-gen', 'hebrew-calendar-m8-gen', 'hebrew-calendar-m9-gen',
|
|
|
|
|
|
'hebrew-calendar-m10-gen', 'hebrew-calendar-m11-gen', 'hebrew-calendar-m12-gen',
|
|
|
|
|
|
'hebrew-calendar-m6a-gen', 'hebrew-calendar-m6b-gen'
|
|
|
|
|
|
);
|
2008-06-19 14:46:50 +00:00
|
|
|
|
|
|
|
|
|
|
static public $mHijriCalendarMonthMsgs = array(
|
|
|
|
|
|
'hijri-calendar-m1', 'hijri-calendar-m2', 'hijri-calendar-m3',
|
|
|
|
|
|
'hijri-calendar-m4', 'hijri-calendar-m5', 'hijri-calendar-m6',
|
|
|
|
|
|
'hijri-calendar-m7', 'hijri-calendar-m8', 'hijri-calendar-m9',
|
|
|
|
|
|
'hijri-calendar-m10', 'hijri-calendar-m11', 'hijri-calendar-m12'
|
|
|
|
|
|
);
|
2007-11-13 17:17:07 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
/**
|
2008-11-12 00:11:10 +00:00
|
|
|
|
* Get a cached language object for a given language code
|
2006-07-26 07:15:39 +00:00
|
|
|
|
*/
|
|
|
|
|
|
static function factory( $code ) {
|
2008-11-12 00:11:10 +00:00
|
|
|
|
if ( !isset( self::$mLangObjCache[$code] ) ) {
|
2008-11-25 19:38:22 +00:00
|
|
|
|
if( count( self::$mLangObjCache ) > 10 ) {
|
|
|
|
|
|
// Don't keep a billion objects around, that's stupid.
|
|
|
|
|
|
self::$mLangObjCache = array();
|
|
|
|
|
|
}
|
2008-11-12 00:11:10 +00:00
|
|
|
|
self::$mLangObjCache[$code] = self::newFromCode( $code );
|
2008-11-11 23:26:07 +00:00
|
|
|
|
}
|
2008-11-12 00:11:10 +00:00
|
|
|
|
return self::$mLangObjCache[$code];
|
|
|
|
|
|
}
|
2008-11-11 23:26:07 +00:00
|
|
|
|
|
2008-11-12 00:11:10 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Create a language object for a given language code
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected static function newFromCode( $code ) {
|
|
|
|
|
|
global $IP;
|
|
|
|
|
|
static $recursionLevel = 0;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ( $code == 'en' ) {
|
|
|
|
|
|
$class = 'Language';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$class = 'Language' . str_replace( '-', '_', ucfirst( $code ) );
|
|
|
|
|
|
// Preload base classes to work around APC/PHP5 bug
|
2006-10-04 01:39:28 +00:00
|
|
|
|
if ( file_exists( "$IP/languages/classes/$class.deps.php" ) ) {
|
|
|
|
|
|
include_once("$IP/languages/classes/$class.deps.php");
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
2006-10-04 01:39:28 +00:00
|
|
|
|
if ( file_exists( "$IP/languages/classes/$class.php" ) ) {
|
|
|
|
|
|
include_once("$IP/languages/classes/$class.php");
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-08-02 17:31:01 +00:00
|
|
|
|
if ( $recursionLevel > 5 ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
throw new MWException( "Language fallback loop detected when creating class $class\n" );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( ! class_exists( $class ) ) {
|
|
|
|
|
|
$fallback = Language::getFallbackFor( $code );
|
|
|
|
|
|
++$recursionLevel;
|
2008-11-12 00:11:10 +00:00
|
|
|
|
$lang = Language::newFromCode( $fallback );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
--$recursionLevel;
|
|
|
|
|
|
$lang->setCode( $code );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$lang = new $class;
|
|
|
|
|
|
}
|
|
|
|
|
|
return $lang;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-06-24 18:48:58 +00:00
|
|
|
|
function __construct() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->mConverter = new FakeConverter($this);
|
|
|
|
|
|
// Set the code to the name of the descendant
|
|
|
|
|
|
if ( get_class( $this ) == 'Language' ) {
|
|
|
|
|
|
$this->mCode = 'en';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$this->mCode = str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
|
|
|
|
|
|
}
|
2004-02-01 22:00:06 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2008-08-26 14:37:15 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Reduce memory usage
|
|
|
|
|
|
*/
|
|
|
|
|
|
function __destruct() {
|
|
|
|
|
|
foreach ( $this as $name => $value ) {
|
|
|
|
|
|
unset( $this->$name );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
2006-07-26 07:15:39 +00:00
|
|
|
|
* Hook which will be called if this is the content language.
|
|
|
|
|
|
* Descendants can use this to register hook functions or modify globals
|
|
|
|
|
|
*/
|
|
|
|
|
|
function initContLang() {}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @deprecated Use User::getDefaultOptions()
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getDefaultUserOptions() {
|
2008-05-21 18:18:58 +00:00
|
|
|
|
wfDeprecated( __METHOD__ );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return User::getDefaultOptions();
|
2004-02-29 08:51:15 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2007-01-20 15:31:32 +00:00
|
|
|
|
function getFallbackLanguageCode() {
|
2008-04-27 14:37:37 +00:00
|
|
|
|
return self::getFallbackFor( $this->mCode );
|
2007-01-20 15:31:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Exports $wgBookstoreListEn
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getBookstoreList() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->bookstoreList;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2005-04-07 19:05:42 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
2003-04-14 23:10:40 +00:00
|
|
|
|
function getNamespaces() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->namespaceNames;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2005-05-03 12:27:30 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* A convenience function that returns the same thing as
|
|
|
|
|
|
* getNamespaces() except with the array values changed to ' '
|
|
|
|
|
|
* where it found '_', useful for producing output to be displayed
|
|
|
|
|
|
* e.g. in <select> forms.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getFormattedNamespaces() {
|
|
|
|
|
|
$ns = $this->getNamespaces();
|
|
|
|
|
|
foreach($ns as $k => $v) {
|
|
|
|
|
|
$ns[$k] = strtr($v, '_', ' ');
|
|
|
|
|
|
}
|
|
|
|
|
|
return $ns;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Get a namespace value by key
|
|
|
|
|
|
* <code>
|
|
|
|
|
|
* $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
|
|
|
|
|
|
* echo $mw_ns; // prints 'MediaWiki'
|
|
|
|
|
|
* </code>
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $index Int: the array key of the namespace to return
|
2005-06-18 04:06:54 +00:00
|
|
|
|
* @return mixed, string if the namespace value exists, otherwise false
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
*/
|
2003-04-14 23:10:40 +00:00
|
|
|
|
function getNsText( $index ) {
|
2005-06-18 04:06:54 +00:00
|
|
|
|
$ns = $this->getNamespaces();
|
|
|
|
|
|
return isset( $ns[$index] ) ? $ns[$index] : false;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2005-05-03 12:27:30 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* A convenience function that returns the same thing as
|
|
|
|
|
|
* getNsText() except with '_' changed to ' ', useful for
|
|
|
|
|
|
* producing output.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getFormattedNsText( $index ) {
|
|
|
|
|
|
$ns = $this->getNsText( $index );
|
|
|
|
|
|
return strtr($ns, '_', ' ');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
2007-04-19 18:47:04 +00:00
|
|
|
|
* Get a namespace key by value, case insensitive.
|
|
|
|
|
|
* Only matches namespace names for the current language, not the
|
|
|
|
|
|
* canonical ones defined in Namespace.php.
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $text String
|
2007-04-19 18:47:04 +00:00
|
|
|
|
* @return mixed An integer if $text is a valid value otherwise false
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getLocalNsIndex( $text ) {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
$lctext = $this->lc($text);
|
|
|
|
|
|
return isset( $this->mNamespaceIds[$lctext] ) ? $this->mNamespaceIds[$lctext] : false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Get a namespace key by value, case insensitive. Canonical namespace
|
|
|
|
|
|
* names override custom ones defined for the current language.
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $text String
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
* @return mixed An integer if $text is a valid value otherwise false
|
|
|
|
|
|
*/
|
2003-04-14 23:10:40 +00:00
|
|
|
|
function getNsIndex( $text ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
2006-11-29 05:45:03 +00:00
|
|
|
|
$lctext = $this->lc($text);
|
2008-03-21 23:13:34 +00:00
|
|
|
|
if( ( $ns = MWNamespace::getCanonicalIndex( $lctext ) ) !== null ) return $ns;
|
2007-04-19 13:40:06 +00:00
|
|
|
|
return isset( $this->mNamespaceIds[$lctext] ) ? $this->mNamespaceIds[$lctext] : false;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
2005-07-03 07:15:53 +00:00
|
|
|
|
* short names for language variants used for language conversion links.
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $code String
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2004-12-24 02:47:38 +00:00
|
|
|
|
function getVariantname( $code ) {
|
2006-08-06 18:32:12 +00:00
|
|
|
|
return $this->getMessageFromDB( "variantname-$code" );
|
2004-12-24 02:47:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
|
function specialPage( $name ) {
|
2006-10-30 06:25:31 +00:00
|
|
|
|
$aliases = $this->getSpecialPageAliases();
|
|
|
|
|
|
if ( isset( $aliases[$name][0] ) ) {
|
|
|
|
|
|
$name = $aliases[$name][0];
|
|
|
|
|
|
}
|
2008-12-25 18:00:26 +00:00
|
|
|
|
return $this->getNsText( NS_SPECIAL ) . ':' . $name;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getQuickbarSettings() {
|
2007-02-22 11:28:05 +00:00
|
|
|
|
return array(
|
|
|
|
|
|
$this->getMessage( 'qbsettings-none' ),
|
|
|
|
|
|
$this->getMessage( 'qbsettings-fixedleft' ),
|
|
|
|
|
|
$this->getMessage( 'qbsettings-fixedright' ),
|
|
|
|
|
|
$this->getMessage( 'qbsettings-floatingleft' ),
|
|
|
|
|
|
$this->getMessage( 'qbsettings-floatingright' )
|
|
|
|
|
|
);
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getMathNames() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->mathNames;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function getDatePreferences() {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->datePreferences;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2003-07-01 12:56:55 +00:00
|
|
|
|
function getDateFormats() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->dateFormats;
|
2003-07-01 12:56:55 +00:00
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2006-08-10 08:00:53 +00:00
|
|
|
|
function getDefaultDateFormat() {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->defaultDateFormat;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function getDatePreferenceMigrationMap() {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->datePreferenceMigrationMap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2008-07-04 10:34:41 +00:00
|
|
|
|
function getImageFile( $image ) {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->imageFiles[$image];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function getDefaultUserOptionOverrides() {
|
|
|
|
|
|
$this->load();
|
2007-09-16 10:17:12 +00:00
|
|
|
|
# XXX - apparently some languageas get empty arrays, didn't get to it yet -- midom
|
|
|
|
|
|
if (is_array($this->defaultUserOptionOverrides)) {
|
|
|
|
|
|
return $this->defaultUserOptionOverrides;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return array();
|
|
|
|
|
|
}
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getExtraUserToggles() {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->extraUserToggles;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2004-04-09 08:27:00 +00:00
|
|
|
|
function getUserToggle( $tog ) {
|
2006-08-06 18:32:12 +00:00
|
|
|
|
return $this->getMessageFromDB( "tog-$tog" );
|
2004-04-09 08:27:00 +00:00
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Get language names, indexed by code.
|
|
|
|
|
|
* If $customisedOnly is true, only returns codes with a messages file
|
|
|
|
|
|
*/
|
2006-12-16 22:03:49 +00:00
|
|
|
|
public static function getLanguageNames( $customisedOnly = false ) {
|
2007-12-06 16:49:48 +00:00
|
|
|
|
global $wgLanguageNames, $wgExtraLanguageNames;
|
|
|
|
|
|
$allNames = $wgExtraLanguageNames + $wgLanguageNames;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ( !$customisedOnly ) {
|
2007-12-06 16:49:48 +00:00
|
|
|
|
return $allNames;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
global $IP;
|
|
|
|
|
|
$names = array();
|
2007-08-08 23:08:54 +00:00
|
|
|
|
$dir = opendir( "$IP/languages/messages" );
|
|
|
|
|
|
while( false !== ( $file = readdir( $dir ) ) ) {
|
2007-01-12 07:26:32 +00:00
|
|
|
|
$m = array();
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if( preg_match( '/Messages([A-Z][a-z_]+)\.php$/', $file, $m ) ) {
|
|
|
|
|
|
$code = str_replace( '_', '-', strtolower( $m[1] ) );
|
2007-12-06 16:49:48 +00:00
|
|
|
|
if ( isset( $allNames[$code] ) ) {
|
|
|
|
|
|
$names[$code] = $allNames[$code];
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-08-08 23:08:54 +00:00
|
|
|
|
closedir( $dir );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $names;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2008-09-30 19:03:22 +00:00
|
|
|
|
* Get a message from the MediaWiki namespace.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param $msg String: message name
|
|
|
|
|
|
* @return string
|
2006-07-26 07:15:39 +00:00
|
|
|
|
*/
|
|
|
|
|
|
function getMessageFromDB( $msg ) {
|
2008-09-30 19:03:22 +00:00
|
|
|
|
return wfMsgExt( $msg, array( 'parsemag', 'language' => $this ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getLanguageName( $code ) {
|
2007-12-06 16:49:48 +00:00
|
|
|
|
$names = self::getLanguageNames();
|
|
|
|
|
|
if ( !array_key_exists( $code, $names ) ) {
|
2005-06-27 02:20:50 +00:00
|
|
|
|
return '';
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2007-12-06 16:49:48 +00:00
|
|
|
|
return $names[$code];
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function getMonthName( $key ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->getMessageFromDB( self::$mMonthMsgs[$key-1] );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function getMonthNameGen( $key ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->getMessageFromDB( self::$mMonthGenMsgs[$key-1] );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function getMonthAbbreviation( $key ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->getMessageFromDB( self::$mMonthAbbrevMsgs[$key-1] );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function getWeekdayName( $key ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->getMessageFromDB( self::$mWeekdayMsgs[$key-1] );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getWeekdayAbbreviation( $key ) {
|
|
|
|
|
|
return $this->getMessageFromDB( self::$mWeekdayAbbrevMsgs[$key-1] );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-13 04:05:13 +00:00
|
|
|
|
function getIranianCalendarMonthName( $key ) {
|
|
|
|
|
|
return $this->getMessageFromDB( self::$mIranianCalendarMonthMsgs[$key-1] );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-13 17:17:07 +00:00
|
|
|
|
function getHebrewCalendarMonthName( $key ) {
|
|
|
|
|
|
return $this->getMessageFromDB( self::$mHebrewCalendarMonthMsgs[$key-1] );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getHebrewCalendarMonthNameGen( $key ) {
|
|
|
|
|
|
return $this->getMessageFromDB( self::$mHebrewCalendarMonthGenMsgs[$key-1] );
|
|
|
|
|
|
}
|
2008-06-19 14:46:50 +00:00
|
|
|
|
|
|
|
|
|
|
function getHijriCalendarMonthName( $key ) {
|
|
|
|
|
|
return $this->getMessageFromDB( self::$mHijriCalendarMonthMsgs[$key-1] );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-04-04 22:58:18 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Used by date() and time() to adjust the time output.
|
2008-05-21 18:18:58 +00:00
|
|
|
|
*
|
|
|
|
|
|
* @param $ts Int the time in date('YmdHis') format
|
|
|
|
|
|
* @param $tz Mixed: adjust the time by this amount (default false, mean we
|
|
|
|
|
|
* get user timecorrection setting)
|
2005-04-04 22:58:18 +00:00
|
|
|
|
* @return int
|
|
|
|
|
|
*/
|
2004-12-18 03:47:11 +00:00
|
|
|
|
function userAdjust( $ts, $tz = false ) {
|
2007-03-27 19:39:37 +00:00
|
|
|
|
global $wgUser, $wgLocalTZoffset;
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2008-12-22 21:55:09 +00:00
|
|
|
|
if ( $tz === false ) {
|
2005-04-01 11:09:47 +00:00
|
|
|
|
$tz = $wgUser->getOption( 'timecorrection' );
|
2004-12-18 03:47:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2008-12-22 21:55:09 +00:00
|
|
|
|
$data = explode( '|', $tz, 3 );
|
2006-04-19 17:57:15 +00:00
|
|
|
|
|
2008-12-22 21:55:09 +00:00
|
|
|
|
if ( $data[0] == 'ZoneInfo' ) {
|
|
|
|
|
|
if ( function_exists( 'timezone_open' ) && @timezone_open( $data[2] ) !== false ) {
|
|
|
|
|
|
$date = date_create( $ts, timezone_open( 'UTC' ) );
|
|
|
|
|
|
date_timezone_set( $date, timezone_open( $data[2] ) );
|
|
|
|
|
|
$date = date_format( $date, 'YmdHis' );
|
|
|
|
|
|
return $date;
|
2006-04-30 12:20:20 +00:00
|
|
|
|
}
|
2008-12-22 21:55:09 +00:00
|
|
|
|
# Unrecognized timezone, default to 'Offset' with the stored offset.
|
|
|
|
|
|
$data[0] = 'Offset';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$minDiff = 0;
|
|
|
|
|
|
if ( $data[0] == 'System' || $tz == '' ) {
|
|
|
|
|
|
# Global offset in minutes.
|
|
|
|
|
|
if( isset($wgLocalTZoffset) ) $minDiff = $wgLocalTZoffset;
|
|
|
|
|
|
} else if ( $data[0] == 'Offset' ) {
|
|
|
|
|
|
$minDiff = intval( $data[1] );
|
2004-01-26 02:55:07 +00:00
|
|
|
|
} else {
|
2008-12-22 21:55:09 +00:00
|
|
|
|
$data = explode( ':', $tz );
|
|
|
|
|
|
if( count( $data ) == 2 ) {
|
|
|
|
|
|
$data[0] = intval( $data[0] );
|
|
|
|
|
|
$data[1] = intval( $data[1] );
|
|
|
|
|
|
$minDiff = abs( $data[0] ) * 60 + $data[1];
|
|
|
|
|
|
if ( $data[0] < 0 ) $minDiff = -$minDiff;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$minDiff = intval( $data[0] ) * 60;
|
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2006-04-19 17:57:15 +00:00
|
|
|
|
|
|
|
|
|
|
# No difference ? Return time unchanged
|
2008-12-22 21:55:09 +00:00
|
|
|
|
if ( 0 == $minDiff ) return $ts;
|
2004-01-26 02:55:07 +00:00
|
|
|
|
|
2007-06-20 22:25:39 +00:00
|
|
|
|
wfSuppressWarnings(); // E_STRICT system time bitching
|
2008-12-22 21:55:09 +00:00
|
|
|
|
# Generate an adjusted date; take advantage of the fact that mktime
|
|
|
|
|
|
# will normalize out-of-range values so we don't have to split $minDiff
|
|
|
|
|
|
# into hours and minutes.
|
2004-07-08 15:40:27 +00:00
|
|
|
|
$t = mktime( (
|
2008-12-22 21:55:09 +00:00
|
|
|
|
(int)substr( $ts, 8, 2) ), # Hours
|
2004-01-26 02:55:07 +00:00
|
|
|
|
(int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
|
|
|
|
|
|
(int)substr( $ts, 12, 2 ), # Seconds
|
|
|
|
|
|
(int)substr( $ts, 4, 2 ), # Month
|
|
|
|
|
|
(int)substr( $ts, 6, 2 ), # Day
|
|
|
|
|
|
(int)substr( $ts, 0, 4 ) ); #Year
|
2007-06-20 20:33:44 +00:00
|
|
|
|
|
|
|
|
|
|
$date = date( 'YmdHis', $t );
|
2007-06-20 22:25:39 +00:00
|
|
|
|
wfRestoreWarnings();
|
2007-06-20 20:33:44 +00:00
|
|
|
|
|
|
|
|
|
|
return $date;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* This is a workalike of PHP's date() function, but with better
|
|
|
|
|
|
* internationalisation, a reduced set of format characters, and a better
|
|
|
|
|
|
* escaping format.
|
|
|
|
|
|
*
|
2006-09-25 05:59:00 +00:00
|
|
|
|
* Supported format characters are dDjlNwzWFmMntLYyaAgGhHiscrU. See the
|
|
|
|
|
|
* PHP manual for definitions. There are a number of extensions, which
|
|
|
|
|
|
* start with "x":
|
2006-07-26 07:15:39 +00:00
|
|
|
|
*
|
|
|
|
|
|
* xn Do not translate digits of the next numeric format character
|
2006-09-25 05:59:00 +00:00
|
|
|
|
* xN Toggle raw digit (xn) flag, stays set until explicitly unset
|
2006-07-26 07:15:39 +00:00
|
|
|
|
* xr Use roman numerals for the next numeric format character
|
2007-11-13 17:17:07 +00:00
|
|
|
|
* xh Use hebrew numerals for the next numeric format character
|
2006-07-26 07:15:39 +00:00
|
|
|
|
* xx Literal x
|
|
|
|
|
|
* xg Genitive month name
|
|
|
|
|
|
*
|
2007-11-13 04:05:13 +00:00
|
|
|
|
* xij j (day number) in Iranian calendar
|
|
|
|
|
|
* xiF F (month name) in Iranian calendar
|
|
|
|
|
|
* xin n (month number) in Iranian calendar
|
|
|
|
|
|
* xiY Y (full year) in Iranian calendar
|
|
|
|
|
|
*
|
2007-11-13 17:17:07 +00:00
|
|
|
|
* xjj j (day number) in Hebrew calendar
|
|
|
|
|
|
* xjF F (month name) in Hebrew calendar
|
2007-12-15 14:35:15 +00:00
|
|
|
|
* xjt t (days in month) in Hebrew calendar
|
2007-11-13 17:17:07 +00:00
|
|
|
|
* xjx xg (genitive month name) in Hebrew calendar
|
|
|
|
|
|
* xjn n (month number) in Hebrew calendar
|
|
|
|
|
|
* xjY Y (full year) in Hebrew calendar
|
|
|
|
|
|
*
|
2008-06-19 14:46:50 +00:00
|
|
|
|
* xmj j (day number) in Hijri calendar
|
|
|
|
|
|
* xmF F (month name) in Hijri calendar
|
|
|
|
|
|
* xmn n (month number) in Hijri calendar
|
|
|
|
|
|
* xmY Y (full year) in Hijri calendar
|
|
|
|
|
|
*
|
2007-12-06 20:14:36 +00:00
|
|
|
|
* xkY Y (full year) in Thai solar calendar. Months and days are
|
|
|
|
|
|
* identical to the Gregorian calendar
|
|
|
|
|
|
*
|
2006-07-26 07:15:39 +00:00
|
|
|
|
* Characters enclosed in double quotes will be considered literal (with
|
|
|
|
|
|
* the quotes themselves removed). Unmatched quotes will be considered
|
|
|
|
|
|
* literal quotes. Example:
|
|
|
|
|
|
*
|
|
|
|
|
|
* "The month is" F => The month is January
|
|
|
|
|
|
* i's" => 20'11"
|
|
|
|
|
|
*
|
|
|
|
|
|
* Backslash escaping is also supported.
|
2007-06-15 19:07:15 +00:00
|
|
|
|
*
|
|
|
|
|
|
* Input timestamp is assumed to be pre-normalized to the desired local
|
|
|
|
|
|
* time zone, if any.
|
2006-07-26 07:15:39 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $format String
|
|
|
|
|
|
* @param $ts String: 14-character timestamp
|
2006-07-26 07:15:39 +00:00
|
|
|
|
* YYYYMMDDHHMMSS
|
|
|
|
|
|
* 01234567890123
|
|
|
|
|
|
*/
|
|
|
|
|
|
function sprintfDate( $format, $ts ) {
|
|
|
|
|
|
$s = '';
|
|
|
|
|
|
$raw = false;
|
|
|
|
|
|
$roman = false;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
$hebrewNum = false;
|
2006-09-25 05:59:00 +00:00
|
|
|
|
$unix = false;
|
|
|
|
|
|
$rawToggle = false;
|
2007-11-13 04:05:13 +00:00
|
|
|
|
$iranian = false;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
$hebrew = false;
|
2008-06-19 14:46:50 +00:00
|
|
|
|
$hijri = false;
|
2007-12-06 20:14:36 +00:00
|
|
|
|
$thai = false;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
for ( $p = 0; $p < strlen( $format ); $p++ ) {
|
|
|
|
|
|
$num = false;
|
|
|
|
|
|
$code = $format[$p];
|
|
|
|
|
|
if ( $code == 'x' && $p < strlen( $format ) - 1 ) {
|
|
|
|
|
|
$code .= $format[++$p];
|
|
|
|
|
|
}
|
2007-11-13 04:05:13 +00:00
|
|
|
|
|
2008-06-19 16:14:48 +00:00
|
|
|
|
if ( ( $code === 'xi' || $code == 'xj' || $code == 'xk' || $code == 'xm' ) && $p < strlen( $format ) - 1 ) {
|
|
|
|
|
|
$code .= $format[++$p];
|
|
|
|
|
|
}
|
2007-11-13 04:05:13 +00:00
|
|
|
|
|
2008-06-19 16:14:48 +00:00
|
|
|
|
switch ( $code ) {
|
|
|
|
|
|
case 'xx':
|
|
|
|
|
|
$s .= 'x';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xn':
|
|
|
|
|
|
$raw = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xN':
|
|
|
|
|
|
$rawToggle = !$rawToggle;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xr':
|
|
|
|
|
|
$roman = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xh':
|
|
|
|
|
|
$hebrewNum = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xg':
|
|
|
|
|
|
$s .= $this->getMonthNameGen( substr( $ts, 4, 2 ) );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xjx':
|
|
|
|
|
|
if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
|
|
|
|
|
|
$s .= $this->getHebrewCalendarMonthNameGen( $hebrew[1] );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'd':
|
|
|
|
|
|
$num = substr( $ts, 6, 2 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'D':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$s .= $this->getWeekdayAbbreviation( gmdate( 'w', $unix ) + 1 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'j':
|
|
|
|
|
|
$num = intval( substr( $ts, 6, 2 ) );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xij':
|
|
|
|
|
|
if ( !$iranian ) $iranian = self::tsToIranian( $ts );
|
|
|
|
|
|
$num = $iranian[2];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xmj':
|
|
|
|
|
|
if ( !$hijri ) $hijri = self::tsToHijri( $ts );
|
|
|
|
|
|
$num = $hijri[2];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xjj':
|
|
|
|
|
|
if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
|
|
|
|
|
|
$num = $hebrew[2];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'l':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$s .= $this->getWeekdayName( gmdate( 'w', $unix ) + 1 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'N':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$w = gmdate( 'w', $unix );
|
|
|
|
|
|
$num = $w ? $w : 7;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'w':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$num = gmdate( 'w', $unix );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'z':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$num = gmdate( 'z', $unix );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'W':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$num = gmdate( 'W', $unix );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'F':
|
|
|
|
|
|
$s .= $this->getMonthName( substr( $ts, 4, 2 ) );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xiF':
|
|
|
|
|
|
if ( !$iranian ) $iranian = self::tsToIranian( $ts );
|
|
|
|
|
|
$s .= $this->getIranianCalendarMonthName( $iranian[1] );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xmF':
|
|
|
|
|
|
if ( !$hijri ) $hijri = self::tsToHijri( $ts );
|
|
|
|
|
|
$s .= $this->getHijriCalendarMonthName( $hijri[1] );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xjF':
|
|
|
|
|
|
if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
|
|
|
|
|
|
$s .= $this->getHebrewCalendarMonthName( $hebrew[1] );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'm':
|
|
|
|
|
|
$num = substr( $ts, 4, 2 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'M':
|
|
|
|
|
|
$s .= $this->getMonthAbbreviation( substr( $ts, 4, 2 ) );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'n':
|
|
|
|
|
|
$num = intval( substr( $ts, 4, 2 ) );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xin':
|
|
|
|
|
|
if ( !$iranian ) $iranian = self::tsToIranian( $ts );
|
|
|
|
|
|
$num = $iranian[1];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xmn':
|
|
|
|
|
|
if ( !$hijri ) $hijri = self::tsToHijri ( $ts );
|
|
|
|
|
|
$num = $hijri[1];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xjn':
|
|
|
|
|
|
if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
|
|
|
|
|
|
$num = $hebrew[1];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 't':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$num = gmdate( 't', $unix );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xjt':
|
|
|
|
|
|
if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
|
|
|
|
|
|
$num = $hebrew[3];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'L':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$num = gmdate( 'L', $unix );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'Y':
|
|
|
|
|
|
$num = substr( $ts, 0, 4 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xiY':
|
|
|
|
|
|
if ( !$iranian ) $iranian = self::tsToIranian( $ts );
|
|
|
|
|
|
$num = $iranian[0];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xmY':
|
|
|
|
|
|
if ( !$hijri ) $hijri = self::tsToHijri( $ts );
|
|
|
|
|
|
$num = $hijri[0];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xjY':
|
|
|
|
|
|
if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
|
|
|
|
|
|
$num = $hebrew[0];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'xkY':
|
|
|
|
|
|
if ( !$thai ) $thai = self::tsToThai( $ts );
|
|
|
|
|
|
$num = $thai[0];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'y':
|
|
|
|
|
|
$num = substr( $ts, 2, 2 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'a':
|
|
|
|
|
|
$s .= intval( substr( $ts, 8, 2 ) ) < 12 ? 'am' : 'pm';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'A':
|
|
|
|
|
|
$s .= intval( substr( $ts, 8, 2 ) ) < 12 ? 'AM' : 'PM';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'g':
|
|
|
|
|
|
$h = substr( $ts, 8, 2 );
|
|
|
|
|
|
$num = $h % 12 ? $h % 12 : 12;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'G':
|
|
|
|
|
|
$num = intval( substr( $ts, 8, 2 ) );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'h':
|
|
|
|
|
|
$h = substr( $ts, 8, 2 );
|
|
|
|
|
|
$num = sprintf( '%02d', $h % 12 ? $h % 12 : 12 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'H':
|
|
|
|
|
|
$num = substr( $ts, 8, 2 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'i':
|
|
|
|
|
|
$num = substr( $ts, 10, 2 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 's':
|
|
|
|
|
|
$num = substr( $ts, 12, 2 );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'c':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$s .= gmdate( 'c', $unix );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'r':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$s .= gmdate( 'r', $unix );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'U':
|
|
|
|
|
|
if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
|
|
|
|
|
|
$num = $unix;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case '\\':
|
|
|
|
|
|
# Backslash escaping
|
|
|
|
|
|
if ( $p < strlen( $format ) - 1 ) {
|
|
|
|
|
|
$s .= $format[++$p];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$s .= '\\';
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case '"':
|
|
|
|
|
|
# Quoted literal
|
|
|
|
|
|
if ( $p < strlen( $format ) - 1 ) {
|
|
|
|
|
|
$endQuote = strpos( $format, '"', $p + 1 );
|
|
|
|
|
|
if ( $endQuote === false ) {
|
|
|
|
|
|
# No terminating quote, assume literal "
|
2008-06-19 15:18:48 +00:00
|
|
|
|
$s .= '"';
|
2008-06-19 16:14:48 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
$s .= substr( $format, $p + 1, $endQuote - $p - 1 );
|
|
|
|
|
|
$p = $endQuote;
|
2008-06-19 15:18:48 +00:00
|
|
|
|
}
|
2006-07-26 07:15:39 +00:00
|
|
|
|
} else {
|
2008-06-19 16:14:48 +00:00
|
|
|
|
# Quote at end of string, assume literal "
|
|
|
|
|
|
$s .= '"';
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
2008-06-19 16:14:48 +00:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
$s .= $format[$p];
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( $num !== false ) {
|
|
|
|
|
|
if ( $rawToggle || $raw ) {
|
|
|
|
|
|
$s .= $num;
|
|
|
|
|
|
$raw = false;
|
|
|
|
|
|
} elseif ( $roman ) {
|
|
|
|
|
|
$s .= self::romanNumeral( $num );
|
|
|
|
|
|
$roman = false;
|
|
|
|
|
|
} elseif( $hebrewNum ) {
|
|
|
|
|
|
$s .= self::hebrewNumeral( $num );
|
|
|
|
|
|
$hebrewNum = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$s .= $this->formatNum( $num, true );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
2008-06-19 16:14:48 +00:00
|
|
|
|
$num = false;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return $s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-13 04:05:13 +00:00
|
|
|
|
private static $GREG_DAYS = array( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
|
|
|
|
|
|
private static $IRANIAN_DAYS = array( 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 );
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Algorithm by Roozbeh Pournader and Mohammad Toossi to convert
|
|
|
|
|
|
* Gregorian dates to Iranian dates. Originally written in C, it
|
|
|
|
|
|
* is released under the terms of GNU Lesser General Public
|
|
|
|
|
|
* License. Conversion to PHP was performed by Niklas Laxström.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Link: http://www.farsiweb.info/jalali/jalali.c
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static function tsToIranian( $ts ) {
|
|
|
|
|
|
$gy = substr( $ts, 0, 4 ) -1600;
|
|
|
|
|
|
$gm = substr( $ts, 4, 2 ) -1;
|
|
|
|
|
|
$gd = substr( $ts, 6, 2 ) -1;
|
|
|
|
|
|
|
|
|
|
|
|
# Days passed from the beginning (including leap years)
|
|
|
|
|
|
$gDayNo = 365*$gy
|
|
|
|
|
|
+ floor(($gy+3) / 4)
|
|
|
|
|
|
- floor(($gy+99) / 100)
|
|
|
|
|
|
+ floor(($gy+399) / 400);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add days of the past months of this year
|
|
|
|
|
|
for( $i = 0; $i < $gm; $i++ ) {
|
|
|
|
|
|
$gDayNo += self::$GREG_DAYS[$i];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Leap years
|
|
|
|
|
|
if ( $gm > 1 && (($gy%4===0 && $gy%100!==0 || ($gy%400==0)))) {
|
|
|
|
|
|
$gDayNo++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Days passed in current month
|
|
|
|
|
|
$gDayNo += $gd;
|
|
|
|
|
|
|
|
|
|
|
|
$jDayNo = $gDayNo - 79;
|
|
|
|
|
|
|
|
|
|
|
|
$jNp = floor($jDayNo / 12053);
|
|
|
|
|
|
$jDayNo %= 12053;
|
|
|
|
|
|
|
|
|
|
|
|
$jy = 979 + 33*$jNp + 4*floor($jDayNo/1461);
|
|
|
|
|
|
$jDayNo %= 1461;
|
|
|
|
|
|
|
|
|
|
|
|
if ( $jDayNo >= 366 ) {
|
|
|
|
|
|
$jy += floor(($jDayNo-1)/365);
|
|
|
|
|
|
$jDayNo = floor(($jDayNo-1)%365);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for ( $i = 0; $i < 11 && $jDayNo >= self::$IRANIAN_DAYS[$i]; $i++ ) {
|
|
|
|
|
|
$jDayNo -= self::$IRANIAN_DAYS[$i];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$jm= $i+1;
|
|
|
|
|
|
$jd= $jDayNo+1;
|
|
|
|
|
|
|
|
|
|
|
|
return array($jy, $jm, $jd);
|
|
|
|
|
|
}
|
2008-06-19 14:46:50 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Converting Gregorian dates to Hijri dates.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Based on a PHP-Nuke block by Sharjeel which is released under GNU/GPL license
|
|
|
|
|
|
*
|
|
|
|
|
|
* @link http://phpnuke.org/modules.php?name=News&file=article&sid=8234&mode=thread&order=0&thold=0
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static function tsToHijri ( $ts ) {
|
|
|
|
|
|
$year = substr( $ts, 0, 4 );
|
|
|
|
|
|
$month = substr( $ts, 4, 2 );
|
|
|
|
|
|
$day = substr( $ts, 6, 2 );
|
|
|
|
|
|
|
|
|
|
|
|
$zyr = $year;
|
|
|
|
|
|
$zd=$day;
|
|
|
|
|
|
$zm=$month;
|
|
|
|
|
|
$zy=$zyr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (($zy>1582)||(($zy==1582)&&($zm>10))||(($zy==1582)&&($zm==10)&&($zd>14)))
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$zjd=(int)((1461*($zy + 4800 + (int)( ($zm-14) /12) ))/4) + (int)((367*($zm-2-12*((int)(($zm-14)/12))))/12)-(int)((3*(int)(( ($zy+4900+(int)(($zm-14)/12))/100)))/4)+$zd-32075;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
$zjd = 367*$zy-(int)((7*($zy+5001+(int)(($zm-9)/7)))/4)+(int)((275*$zm)/9)+$zd+1729777;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$zl=$zjd-1948440+10632;
|
|
|
|
|
|
$zn=(int)(($zl-1)/10631);
|
|
|
|
|
|
$zl=$zl-10631*$zn+354;
|
|
|
|
|
|
$zj=((int)((10985-$zl)/5316))*((int)((50*$zl)/17719))+((int)($zl/5670))*((int)((43*$zl)/15238));
|
|
|
|
|
|
$zl=$zl-((int)((30-$zj)/15))*((int)((17719*$zj)/50))-((int)($zj/16))*((int)((15238*$zj)/43))+29;
|
|
|
|
|
|
$zm=(int)((24*$zl)/709);
|
|
|
|
|
|
$zd=$zl-(int)((709*$zm)/24);
|
|
|
|
|
|
$zy=30*$zn+$zj-30;
|
|
|
|
|
|
|
|
|
|
|
|
return array ($zy, $zm, $zd);
|
|
|
|
|
|
}
|
2007-11-13 04:05:13 +00:00
|
|
|
|
|
2007-11-13 17:17:07 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Converting Gregorian dates to Hebrew dates.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Based on a JavaScript code by Abu Mami and Yisrael Hersch
|
|
|
|
|
|
* (abu-mami@kaluach.net, http://www.kaluach.net), who permitted
|
|
|
|
|
|
* to translate the relevant functions into PHP and release them under
|
|
|
|
|
|
* GNU GPL.
|
2008-08-04 00:53:13 +00:00
|
|
|
|
*
|
2008-08-06 20:06:22 +00:00
|
|
|
|
* The months are counted from Tishrei = 1. In a leap year, Adar I is 13
|
|
|
|
|
|
* and Adar II is 14. In a non-leap year, Adar is 6.
|
2007-11-13 17:17:07 +00:00
|
|
|
|
*/
|
|
|
|
|
|
private static function tsToHebrew( $ts ) {
|
|
|
|
|
|
# Parse date
|
|
|
|
|
|
$year = substr( $ts, 0, 4 );
|
|
|
|
|
|
$month = substr( $ts, 4, 2 );
|
|
|
|
|
|
$day = substr( $ts, 6, 2 );
|
|
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Calculate Hebrew year
|
|
|
|
|
|
$hebrewYear = $year + 3760;
|
|
|
|
|
|
|
|
|
|
|
|
# Month number when September = 1, August = 12
|
|
|
|
|
|
$month += 4;
|
|
|
|
|
|
if( $month > 12 ) {
|
|
|
|
|
|
# Next year
|
|
|
|
|
|
$month -= 12;
|
|
|
|
|
|
$year++;
|
|
|
|
|
|
$hebrewYear++;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Calculate day of year from 1 September
|
|
|
|
|
|
$dayOfYear = $day;
|
|
|
|
|
|
for( $i = 1; $i < $month; $i++ ) {
|
|
|
|
|
|
if( $i == 6 ) {
|
|
|
|
|
|
# February
|
|
|
|
|
|
$dayOfYear += 28;
|
|
|
|
|
|
# Check if the year is leap
|
|
|
|
|
|
if( $year % 400 == 0 || ( $year % 4 == 0 && $year % 100 > 0 ) ) {
|
|
|
|
|
|
$dayOfYear++;
|
|
|
|
|
|
}
|
|
|
|
|
|
} elseif( $i == 8 || $i == 10 || $i == 1 || $i == 3 ) {
|
|
|
|
|
|
$dayOfYear += 30;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$dayOfYear += 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Calculate the start of the Hebrew year
|
|
|
|
|
|
$start = self::hebrewYearStart( $hebrewYear );
|
|
|
|
|
|
|
|
|
|
|
|
# Calculate next year's start
|
|
|
|
|
|
if( $dayOfYear <= $start ) {
|
|
|
|
|
|
# Day is before the start of the year - it is the previous year
|
|
|
|
|
|
# Next year's start
|
|
|
|
|
|
$nextStart = $start;
|
|
|
|
|
|
# Previous year
|
|
|
|
|
|
$year--;
|
|
|
|
|
|
$hebrewYear--;
|
|
|
|
|
|
# Add days since previous year's 1 September
|
2007-12-15 14:35:15 +00:00
|
|
|
|
$dayOfYear += 365;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
if( ( $year % 400 == 0 ) || ( $year % 100 != 0 && $year % 4 == 0 ) ) {
|
|
|
|
|
|
# Leap year
|
2007-12-15 14:35:15 +00:00
|
|
|
|
$dayOfYear++;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
}
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Start of the new (previous) year
|
|
|
|
|
|
$start = self::hebrewYearStart( $hebrewYear );
|
2007-11-13 17:17:07 +00:00
|
|
|
|
} else {
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Next year's start
|
|
|
|
|
|
$nextStart = self::hebrewYearStart( $hebrewYear + 1 );
|
2007-11-13 17:17:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Calculate Hebrew day of year
|
|
|
|
|
|
$hebrewDayOfYear = $dayOfYear - $start;
|
|
|
|
|
|
|
|
|
|
|
|
# Difference between year's days
|
|
|
|
|
|
$diff = $nextStart - $start;
|
|
|
|
|
|
# Add 12 (or 13 for leap years) days to ignore the difference between
|
|
|
|
|
|
# Hebrew and Gregorian year (353 at least vs. 365/6) - now the
|
|
|
|
|
|
# difference is only about the year type
|
|
|
|
|
|
if( ( $year % 400 == 0 ) || ( $year % 100 != 0 && $year % 4 == 0 ) ) {
|
|
|
|
|
|
$diff += 13;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$diff += 12;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Check the year pattern, and is leap year
|
2007-12-15 14:35:15 +00:00
|
|
|
|
# 0 means an incomplete year, 1 means a regular year, 2 means a complete year
|
|
|
|
|
|
# This is mod 30, to work on both leap years (which add 30 days of Adar I)
|
|
|
|
|
|
# and non-leap years
|
2007-12-20 15:59:39 +00:00
|
|
|
|
$yearPattern = $diff % 30;
|
|
|
|
|
|
# Check if leap year
|
|
|
|
|
|
$isLeap = $diff >= 30;
|
2007-12-15 14:35:15 +00:00
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Calculate day in the month from number of day in the Hebrew year
|
2007-12-15 14:35:15 +00:00
|
|
|
|
# Don't check Adar - if the day is not in Adar, we will stop before;
|
|
|
|
|
|
# if it is in Adar, we will use it to check if it is Adar I or Adar II
|
2007-12-20 15:59:39 +00:00
|
|
|
|
$hebrewDay = $hebrewDayOfYear;
|
|
|
|
|
|
$hebrewMonth = 1;
|
|
|
|
|
|
$days = 0;
|
|
|
|
|
|
while( $hebrewMonth <= 12 ) {
|
2007-11-13 17:17:07 +00:00
|
|
|
|
# Calculate days in this month
|
2007-12-20 15:59:39 +00:00
|
|
|
|
if( $isLeap && $hebrewMonth == 6 ) {
|
|
|
|
|
|
# Adar in a leap year
|
|
|
|
|
|
if( $isLeap ) {
|
|
|
|
|
|
# Leap year - has Adar I, with 30 days, and Adar II, with 29 days
|
|
|
|
|
|
$days = 30;
|
|
|
|
|
|
if( $hebrewDay <= $days ) {
|
|
|
|
|
|
# Day in Adar I
|
|
|
|
|
|
$hebrewMonth = 13;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
# Subtract the days of Adar I
|
|
|
|
|
|
$hebrewDay -= $days;
|
|
|
|
|
|
# Try Adar II
|
|
|
|
|
|
$days = 29;
|
|
|
|
|
|
if( $hebrewDay <= $days ) {
|
|
|
|
|
|
# Day in Adar II
|
|
|
|
|
|
$hebrewMonth = 14;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} elseif( $hebrewMonth == 2 && $yearPattern == 2 ) {
|
2007-11-13 17:17:07 +00:00
|
|
|
|
# Cheshvan in a complete year (otherwise as the rule below)
|
|
|
|
|
|
$days = 30;
|
2007-12-20 15:59:39 +00:00
|
|
|
|
} elseif( $hebrewMonth == 3 && $yearPattern == 0 ) {
|
2007-11-13 17:17:07 +00:00
|
|
|
|
# Kislev in an incomplete year (otherwise as the rule below)
|
|
|
|
|
|
$days = 29;
|
|
|
|
|
|
} else {
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Odd months have 30 days, even have 29
|
|
|
|
|
|
$days = 30 - ( $hebrewMonth - 1 ) % 2;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
}
|
2007-12-20 15:59:39 +00:00
|
|
|
|
if( $hebrewDay <= $days ) {
|
|
|
|
|
|
# In the current month
|
2007-11-13 17:17:07 +00:00
|
|
|
|
break;
|
|
|
|
|
|
} else {
|
2007-12-20 15:59:39 +00:00
|
|
|
|
# Subtract the days of the current month
|
|
|
|
|
|
$hebrewDay -= $days;
|
|
|
|
|
|
# Try in the next month
|
|
|
|
|
|
$hebrewMonth++;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
return array( $hebrewYear, $hebrewMonth, $hebrewDay, $days );
|
2007-12-06 20:14:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-13 17:17:07 +00:00
|
|
|
|
/**
|
2007-12-20 15:59:39 +00:00
|
|
|
|
* This calculates the Hebrew year start, as days since 1 September.
|
2007-11-13 17:17:07 +00:00
|
|
|
|
* Based on Carl Friedrich Gauss algorithm for finding Easter date.
|
|
|
|
|
|
* Used for Hebrew date.
|
|
|
|
|
|
*/
|
2007-12-20 15:59:39 +00:00
|
|
|
|
private static function hebrewYearStart( $year ) {
|
|
|
|
|
|
$a = intval( ( 12 * ( $year - 1 ) + 17 ) % 19 );
|
|
|
|
|
|
$b = intval( ( $year - 1 ) % 4 );
|
|
|
|
|
|
$m = 32.044093161144 + 1.5542417966212 * $a + $b / 4.0 - 0.0031777940220923 * ( $year - 1 );
|
2007-11-13 17:17:07 +00:00
|
|
|
|
if( $m < 0 ) {
|
|
|
|
|
|
$m--;
|
|
|
|
|
|
}
|
2007-11-22 09:17:13 +00:00
|
|
|
|
$Mar = intval( $m );
|
2007-11-13 17:17:07 +00:00
|
|
|
|
if( $m < 0 ) {
|
|
|
|
|
|
$m++;
|
|
|
|
|
|
}
|
|
|
|
|
|
$m -= $Mar;
|
|
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
$c = intval( ( $Mar + 3 * ( $year - 1 ) + 5 * $b + 5 ) % 7);
|
2007-11-13 17:17:07 +00:00
|
|
|
|
if( $c == 0 && $a > 11 && $m >= 0.89772376543210 ) {
|
|
|
|
|
|
$Mar++;
|
|
|
|
|
|
} else if( $c == 1 && $a > 6 && $m >= 0.63287037037037 ) {
|
|
|
|
|
|
$Mar += 2;
|
|
|
|
|
|
} else if( $c == 2 || $c == 4 || $c == 6 ) {
|
|
|
|
|
|
$Mar++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-20 15:59:39 +00:00
|
|
|
|
$Mar += intval( ( $year - 3761 ) / 100 ) - intval( ( $year - 3761 ) / 400 ) - 24;
|
2007-11-13 17:17:07 +00:00
|
|
|
|
return $Mar;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-15 14:35:15 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Algorithm to convert Gregorian dates to Thai solar dates.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Link: http://en.wikipedia.org/wiki/Thai_solar_calendar
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $ts String: 14-character timestamp
|
2007-12-15 14:35:15 +00:00
|
|
|
|
* @return array converted year, month, day
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static function tsToThai( $ts ) {
|
|
|
|
|
|
$gy = substr( $ts, 0, 4 );
|
|
|
|
|
|
$gm = substr( $ts, 4, 2 );
|
|
|
|
|
|
$gd = substr( $ts, 6, 2 );
|
|
|
|
|
|
|
|
|
|
|
|
# Add 543 years to the Gregorian calendar
|
|
|
|
|
|
# Months and days are identical
|
|
|
|
|
|
$gy_thai = $gy + 543;
|
|
|
|
|
|
|
|
|
|
|
|
return array( $gy_thai, $gm, $gd );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
/**
|
2006-09-25 05:59:00 +00:00
|
|
|
|
* Roman number formatting up to 3000
|
2006-07-26 07:15:39 +00:00
|
|
|
|
*/
|
|
|
|
|
|
static function romanNumeral( $num ) {
|
2006-09-25 05:59:00 +00:00
|
|
|
|
static $table = array(
|
|
|
|
|
|
array( '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X' ),
|
|
|
|
|
|
array( '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', 'C' ),
|
|
|
|
|
|
array( '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', 'M' ),
|
|
|
|
|
|
array( '', 'M', 'MM', 'MMM' )
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$num = intval( $num );
|
2006-09-25 05:59:00 +00:00
|
|
|
|
if ( $num > 3000 || $num <= 0 ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $num;
|
|
|
|
|
|
}
|
2006-09-25 05:59:00 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$s = '';
|
2006-09-25 05:59:00 +00:00
|
|
|
|
for ( $pow10 = 1000, $i = 3; $i >= 0; $pow10 /= 10, $i-- ) {
|
|
|
|
|
|
if ( $num >= $pow10 ) {
|
|
|
|
|
|
$s .= $table[$i][floor($num / $pow10)];
|
|
|
|
|
|
}
|
|
|
|
|
|
$num = $num % $pow10;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
return $s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-13 17:17:07 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Hebrew Gematria number formatting up to 9999
|
|
|
|
|
|
*/
|
|
|
|
|
|
static function hebrewNumeral( $num ) {
|
|
|
|
|
|
static $table = array(
|
|
|
|
|
|
array( '', 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י' ),
|
|
|
|
|
|
array( '', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ', 'ק' ),
|
|
|
|
|
|
array( '', 'ק', 'ר', 'ש', 'ת', 'תק', 'תר', 'תש', 'תת', 'תתק', 'תתר' ),
|
|
|
|
|
|
array( '', 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י' )
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
$num = intval( $num );
|
|
|
|
|
|
if ( $num > 9999 || $num <= 0 ) {
|
|
|
|
|
|
return $num;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$s = '';
|
|
|
|
|
|
for ( $pow10 = 1000, $i = 3; $i >= 0; $pow10 /= 10, $i-- ) {
|
|
|
|
|
|
if ( $num >= $pow10 ) {
|
|
|
|
|
|
if ( $num == 15 || $num == 16 ) {
|
2007-11-22 09:17:13 +00:00
|
|
|
|
$s .= $table[0][9] . $table[0][$num - 9];
|
2007-11-13 17:17:07 +00:00
|
|
|
|
$num = 0;
|
|
|
|
|
|
} else {
|
2007-11-22 09:17:13 +00:00
|
|
|
|
$s .= $table[$i][intval( ( $num / $pow10 ) )];
|
2007-11-13 17:17:07 +00:00
|
|
|
|
if( $pow10 == 1000 ) {
|
|
|
|
|
|
$s .= "'";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
$num = $num % $pow10;
|
|
|
|
|
|
}
|
|
|
|
|
|
if( strlen( $s ) == 2 ) {
|
|
|
|
|
|
$str = $s . "'";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$str = substr( $s, 0, strlen( $s ) - 2 ) . '"';
|
|
|
|
|
|
$str .= substr( $s, strlen( $s ) - 2, 2 );
|
|
|
|
|
|
}
|
2007-11-24 11:29:19 +00:00
|
|
|
|
$start = substr( $str, 0, strlen( $str ) - 2 );
|
|
|
|
|
|
$end = substr( $str, strlen( $str ) - 2 );
|
|
|
|
|
|
switch( $end ) {
|
|
|
|
|
|
case 'כ':
|
|
|
|
|
|
$str = $start . 'ך';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'מ':
|
|
|
|
|
|
$str = $start . 'ם';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'נ':
|
|
|
|
|
|
$str = $start . 'ן';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'פ':
|
|
|
|
|
|
$str = $start . 'ף';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'צ':
|
|
|
|
|
|
$str = $start . 'ץ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2007-11-13 17:17:07 +00:00
|
|
|
|
return $str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-04-07 19:05:42 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* This is meant to be used by time(), date(), and timeanddate() to get
|
|
|
|
|
|
* the date preference they're supposed to use, it should be used in
|
|
|
|
|
|
* all children.
|
|
|
|
|
|
*
|
|
|
|
|
|
*<code>
|
2005-09-13 06:55:43 +00:00
|
|
|
|
* function timeanddate([...], $format = true) {
|
2005-04-07 19:05:42 +00:00
|
|
|
|
* $datePreference = $this->dateFormat($format);
|
|
|
|
|
|
* [...]
|
2006-07-26 07:15:39 +00:00
|
|
|
|
* }
|
2005-04-07 19:05:42 +00:00
|
|
|
|
*</code>
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $usePrefs Mixed: if true, the user's preference is used
|
2005-11-08 00:57:09 +00:00
|
|
|
|
* if false, the site/language default is used
|
|
|
|
|
|
* if int/string, assumed to be a format.
|
2005-04-07 19:05:42 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2005-09-13 06:55:43 +00:00
|
|
|
|
function dateFormat( $usePrefs = true ) {
|
2006-01-10 17:46:23 +00:00
|
|
|
|
global $wgUser;
|
2005-04-13 08:37:03 +00:00
|
|
|
|
|
2005-11-08 00:57:09 +00:00
|
|
|
|
if( is_bool( $usePrefs ) ) {
|
|
|
|
|
|
if( $usePrefs ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$datePreference = $wgUser->getDatePreference();
|
2005-11-08 00:57:09 +00:00
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$options = User::getDefaultOptions();
|
2005-11-08 00:57:09 +00:00
|
|
|
|
$datePreference = (string)$options['date'];
|
|
|
|
|
|
}
|
2005-04-13 08:37:03 +00:00
|
|
|
|
} else {
|
2005-11-08 00:57:09 +00:00
|
|
|
|
$datePreference = (string)$usePrefs;
|
2005-04-07 19:05:42 +00:00
|
|
|
|
}
|
2005-09-13 06:55:43 +00:00
|
|
|
|
|
2006-01-10 12:22:58 +00:00
|
|
|
|
// return int
|
|
|
|
|
|
if( $datePreference == '' ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return 'default';
|
2005-09-13 06:55:43 +00:00
|
|
|
|
}
|
2006-01-10 12:22:58 +00:00
|
|
|
|
|
2005-09-13 06:55:43 +00:00
|
|
|
|
return $datePreference;
|
2005-04-07 19:05:42 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2005-04-04 22:58:18 +00:00
|
|
|
|
/**
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $ts Mixed: the time format which needs to be turned into a
|
|
|
|
|
|
* date('YmdHis') format with wfTimestamp(TS_MW,$ts)
|
|
|
|
|
|
* @param $adj Bool: whether to adjust the time output according to the
|
|
|
|
|
|
* user configured offset ($timecorrection)
|
|
|
|
|
|
* @param $format Mixed: true to use user's date format preference
|
|
|
|
|
|
* @param $timecorrection String: the time offset as returned by
|
|
|
|
|
|
* validateTimeZone() in Special:Preferences
|
2005-04-04 22:58:18 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2005-05-08 15:58:52 +00:00
|
|
|
|
function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
if ( $adj ) {
|
|
|
|
|
|
$ts = $this->userAdjust( $ts, $timecorrection );
|
2006-01-10 12:22:58 +00:00
|
|
|
|
}
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$pref = $this->dateFormat( $format );
|
|
|
|
|
|
if( $pref == 'default' || !isset( $this->dateFormats["$pref date"] ) ) {
|
|
|
|
|
|
$pref = $this->defaultDateFormat;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->sprintfDate( $this->dateFormats["$pref date"], $ts );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2005-04-04 22:58:18 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $ts Mixed: the time format which needs to be turned into a
|
|
|
|
|
|
* date('YmdHis') format with wfTimestamp(TS_MW,$ts)
|
|
|
|
|
|
* @param $adj Bool: whether to adjust the time output according to the
|
|
|
|
|
|
* user configured offset ($timecorrection)
|
|
|
|
|
|
* @param $format Mixed: true to use user's date format preference
|
|
|
|
|
|
* @param $timecorrection String: the time offset as returned by
|
|
|
|
|
|
* validateTimeZone() in Special:Preferences
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2005-05-08 11:03:13 +00:00
|
|
|
|
function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
if ( $adj ) {
|
|
|
|
|
|
$ts = $this->userAdjust( $ts, $timecorrection );
|
2004-04-03 00:53:17 +00:00
|
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$pref = $this->dateFormat( $format );
|
|
|
|
|
|
if( $pref == 'default' || !isset( $this->dateFormats["$pref time"] ) ) {
|
|
|
|
|
|
$pref = $this->defaultDateFormat;
|
|
|
|
|
|
}
|
|
|
|
|
|
return $this->sprintfDate( $this->dateFormats["$pref time"], $ts );
|
2005-11-08 00:57:09 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2005-04-04 22:58:18 +00:00
|
|
|
|
/**
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $ts Mixed: the time format which needs to be turned into a
|
|
|
|
|
|
* date('YmdHis') format with wfTimestamp(TS_MW,$ts)
|
|
|
|
|
|
* @param $adj Bool: whether to adjust the time output according to the
|
|
|
|
|
|
* user configured offset ($timecorrection)
|
|
|
|
|
|
* @param $format Mixed: what format to return, if it's false output the
|
|
|
|
|
|
* default one (default true)
|
|
|
|
|
|
* @param $timecorrection String: the time offset as returned by
|
|
|
|
|
|
* validateTimeZone() in Special:Preferences
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2005-05-08 16:02:07 +00:00
|
|
|
|
function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
2007-03-28 19:54:45 +00:00
|
|
|
|
|
|
|
|
|
|
$ts = wfTimestamp( TS_MW, $ts );
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ( $adj ) {
|
|
|
|
|
|
$ts = $this->userAdjust( $ts, $timecorrection );
|
|
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$pref = $this->dateFormat( $format );
|
|
|
|
|
|
if( $pref == 'default' || !isset( $this->dateFormats["$pref both"] ) ) {
|
|
|
|
|
|
$pref = $this->defaultDateFormat;
|
2004-12-18 03:47:11 +00:00
|
|
|
|
}
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
|
|
|
|
|
return $this->sprintfDate( $this->dateFormats["$pref both"], $ts );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function getMessage( $key ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
2006-11-29 05:45:03 +00:00
|
|
|
|
return isset( $this->messages[$key] ) ? $this->messages[$key] : null;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function getAllMessages() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->messages;
|
2003-09-21 13:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
|
function iconv( $in, $out, $string ) {
|
|
|
|
|
|
# For most languages, this is a wrapper for iconv
|
Prevent some unnecessary lstat system calls, generated by include or require directives.
This can be done either by:
* Using explicit full paths, using the $IP global for the installation directory full path, and then working down the tree from there.
* Using explicit full paths, using the "dirname(__FILE__)" directive to get a full directory path for the includer file.
* Occasionally removing the line altogether, and then for some files the inclusion is handled by the autoloader.
For example, if the "extensions/wikihiero/wh_main.php" file does an include or require on "wh_list.php", then PHP does the following:
* tries to open "wiki/wh_list.php", and fails.
* tries to open "wiki/includes/wh_list.php", and fails.
* tries to open "wiki/languages/wh_list.php", and fails.
* tries to open "wiki/extensions/wikihiero/wh_list.php", and succeeds.
So in this example, the first 3 calls can be prevented if PHP is told where the file is.
Testing Method: On a Linux box, run these commands to attach strace to all the apache2 processes, and log their system calls to a temporary file, then generate some activity, and then stop the strace:
-----------------------------------
rm /tmp/strace-log.txt
strace -tt -o /tmp/strace-log.txt -p `pidof apache2 | sed 's/ / -p /g'` &
php maintenance/fuzz-tester.php --keep-passed-tests --include-binary --max-runtime=3 > /tmp/strace-tests.txt
killall -9 strace
grep "No such file or directory" /tmp/strace-log.txt | sort -u
-----------------------------------
Any failed file stats will be marked with: "-1 ENOENT (No such file or directory)".
Also:
* Strict Standards: Undefined offset: 230 in includes/normal/UtfNormal.php on line 637
* Strict Standards: iconv() [<a href='function.iconv'>function.iconv</a>]: Detected an illegal character in input string in languages/Language.php on line 776
[Note: Partial only - despite adding "//IGNORE", it still seems to be possible with some
messed- up binary input to cause PHP 5.1.2's iconv() function to squeal like a stuck pig].
* Update one $fname variable (method belongs to HistoryBlobStub class).
2007-02-09 05:36:56 +00:00
|
|
|
|
return iconv( $in, $out . '//IGNORE', $string );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2006-09-20 10:22:12 +00:00
|
|
|
|
// callback functions for uc(), lc(), ucwords(), ucwordbreaks()
|
|
|
|
|
|
function ucwordbreaksCallbackAscii($matches){
|
|
|
|
|
|
return $this->ucfirst($matches[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function ucwordbreaksCallbackMB($matches){
|
|
|
|
|
|
return mb_strtoupper($matches[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function ucCallback($matches){
|
2006-09-20 20:05:32 +00:00
|
|
|
|
list( $wikiUpperChars ) = self::getCaseMaps();
|
|
|
|
|
|
return strtr( $matches[1], $wikiUpperChars );
|
2006-09-20 10:22:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function lcCallback($matches){
|
2006-09-20 20:05:32 +00:00
|
|
|
|
list( , $wikiLowerChars ) = self::getCaseMaps();
|
|
|
|
|
|
return strtr( $matches[1], $wikiLowerChars );
|
2006-09-20 10:22:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function ucwordsCallbackMB($matches){
|
|
|
|
|
|
return mb_strtoupper($matches[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function ucwordsCallbackWiki($matches){
|
2006-09-20 20:05:32 +00:00
|
|
|
|
list( $wikiUpperChars ) = self::getCaseMaps();
|
|
|
|
|
|
return strtr( $matches[0], $wikiUpperChars );
|
2006-09-20 10:22:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function ucfirst( $str ) {
|
2007-11-13 15:07:54 +00:00
|
|
|
|
if ( empty($str) ) return $str;
|
2007-11-12 22:17:50 +00:00
|
|
|
|
if ( ord($str[0]) < 128 ) return ucfirst($str);
|
|
|
|
|
|
else return self::uc($str,true); // fall back to more complex logic in case of multibyte strings
|
2006-06-09 23:23:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function uc( $str, $first = false ) {
|
2007-01-12 07:26:32 +00:00
|
|
|
|
if ( function_exists( 'mb_strtoupper' ) ) {
|
|
|
|
|
|
if ( $first ) {
|
|
|
|
|
|
if ( self::isMultibyte( $str ) ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return mb_strtoupper( mb_substr( $str, 0, 1 ) ) . mb_substr( $str, 1 );
|
2007-01-12 07:26:32 +00:00
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return ucfirst( $str );
|
2007-01-12 07:26:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return self::isMultibyte( $str ) ? mb_strtoupper( $str ) : strtoupper( $str );
|
2007-01-12 07:26:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ( self::isMultibyte( $str ) ) {
|
|
|
|
|
|
list( $wikiUpperChars ) = $this->getCaseMaps();
|
|
|
|
|
|
$x = $first ? '^' : '';
|
2006-09-20 10:22:12 +00:00
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
|
"/$x([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)/",
|
|
|
|
|
|
array($this,"ucCallback"),
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$str
|
|
|
|
|
|
);
|
2007-01-12 07:26:32 +00:00
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $first ? ucfirst( $str ) : strtoupper( $str );
|
2007-01-12 07:26:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function lcfirst( $str ) {
|
2007-11-13 15:07:54 +00:00
|
|
|
|
if ( empty($str) ) return $str;
|
2007-11-16 23:10:07 +00:00
|
|
|
|
if ( is_string( $str ) && ord($str[0]) < 128 ) {
|
2007-11-12 22:34:39 +00:00
|
|
|
|
// editing string in place = cool
|
|
|
|
|
|
$str[0]=strtolower($str[0]);
|
|
|
|
|
|
return $str;
|
|
|
|
|
|
}
|
|
|
|
|
|
else return self::lc( $str, true );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function lc( $str, $first = false ) {
|
|
|
|
|
|
if ( function_exists( 'mb_strtolower' ) )
|
|
|
|
|
|
if ( $first )
|
|
|
|
|
|
if ( self::isMultibyte( $str ) )
|
|
|
|
|
|
return mb_strtolower( mb_substr( $str, 0, 1 ) ) . mb_substr( $str, 1 );
|
|
|
|
|
|
else
|
|
|
|
|
|
return strtolower( substr( $str, 0, 1 ) ) . substr( $str, 1 );
|
|
|
|
|
|
else
|
|
|
|
|
|
return self::isMultibyte( $str ) ? mb_strtolower( $str ) : strtolower( $str );
|
|
|
|
|
|
else
|
|
|
|
|
|
if ( self::isMultibyte( $str ) ) {
|
|
|
|
|
|
list( , $wikiLowerChars ) = self::getCaseMaps();
|
|
|
|
|
|
$x = $first ? '^' : '';
|
2006-09-20 10:22:12 +00:00
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
|
"/$x([A-Z]|[\\xc0-\\xff][\\x80-\\xbf]*)/",
|
|
|
|
|
|
array($this,"lcCallback"),
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$str
|
|
|
|
|
|
);
|
|
|
|
|
|
} else
|
|
|
|
|
|
return $first ? strtolower( substr( $str, 0, 1 ) ) . substr( $str, 1 ) : strtolower( $str );
|
2006-06-09 23:23:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function isMultibyte( $str ) {
|
2006-08-17 23:48:11 +00:00
|
|
|
|
return (bool)preg_match( '/[\x80-\xff]/', $str );
|
2005-10-22 19:39:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-20 10:22:12 +00:00
|
|
|
|
function ucwords($str) {
|
|
|
|
|
|
if ( self::isMultibyte( $str ) ) {
|
|
|
|
|
|
$str = self::lc($str);
|
|
|
|
|
|
|
|
|
|
|
|
// regexp to find first letter in each word (i.e. after each space)
|
|
|
|
|
|
$replaceRegexp = "/^([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)| ([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)/";
|
|
|
|
|
|
|
|
|
|
|
|
// function to use to capitalize a single char
|
|
|
|
|
|
if ( function_exists( 'mb_strtoupper' ) )
|
|
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
|
$replaceRegexp,
|
|
|
|
|
|
array($this,"ucwordsCallbackMB"),
|
|
|
|
|
|
$str
|
|
|
|
|
|
);
|
|
|
|
|
|
else
|
|
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
|
$replaceRegexp,
|
|
|
|
|
|
array($this,"ucwordsCallbackWiki"),
|
|
|
|
|
|
$str
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
return ucwords( strtolower( $str ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# capitalize words at word breaks
|
|
|
|
|
|
function ucwordbreaks($str){
|
|
|
|
|
|
if (self::isMultibyte( $str ) ) {
|
|
|
|
|
|
$str = self::lc($str);
|
|
|
|
|
|
|
|
|
|
|
|
// since \b doesn't work for UTF-8, we explicitely define word break chars
|
|
|
|
|
|
$breaks= "[ \-\(\)\}\{\.,\?!]";
|
|
|
|
|
|
|
|
|
|
|
|
// find first letter after word break
|
|
|
|
|
|
$replaceRegexp = "/^([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)|$breaks([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)/";
|
|
|
|
|
|
|
|
|
|
|
|
if ( function_exists( 'mb_strtoupper' ) )
|
|
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
|
$replaceRegexp,
|
|
|
|
|
|
array($this,"ucwordbreaksCallbackMB"),
|
|
|
|
|
|
$str
|
|
|
|
|
|
);
|
|
|
|
|
|
else
|
|
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
|
$replaceRegexp,
|
|
|
|
|
|
array($this,"ucwordsCallbackWiki"),
|
|
|
|
|
|
$str
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
|
'/\b([\w\x80-\xff]+)\b/',
|
|
|
|
|
|
array($this,"ucwordbreaksCallbackAscii"),
|
|
|
|
|
|
$str );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-10-30 06:25:31 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Return a case-folded representation of $s
|
|
|
|
|
|
*
|
|
|
|
|
|
* This is a representation such that caseFold($s1)==caseFold($s2) if $s1
|
|
|
|
|
|
* and $s2 are the same except for the case of their characters. It is not
|
|
|
|
|
|
* necessary for the value returned to make sense when displayed.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Do *not* perform any other normalisation in this function. If a caller
|
|
|
|
|
|
* uses this function when it should be using a more general normalisation
|
|
|
|
|
|
* function, then fix the caller.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function caseFold( $s ) {
|
|
|
|
|
|
return $this->uc( $s );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
|
function checkTitleEncoding( $s ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if( is_array( $s ) ) {
|
|
|
|
|
|
wfDebugDieBacktrace( 'Given array to checkTitleEncoding.' );
|
|
|
|
|
|
}
|
|
|
|
|
|
# Check for non-UTF-8 URLs
|
2004-08-14 22:30:10 +00:00
|
|
|
|
$ishigh = preg_match( '/[\x80-\xff]/', $s);
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if(!$ishigh) return $s;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$isutf8 = preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
|
|
|
|
|
|
'[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
|
|
|
|
|
|
if( $isutf8 ) return $s;
|
2004-07-08 15:40:27 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->iconv( $this->fallback8bitEncoding(), "utf-8", $s );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function fallback8bitEncoding() {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->fallback8bitEncoding;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Some languages have special punctuation to strip out
|
|
|
|
|
|
* or characters which need to be converted for MySQL's
|
|
|
|
|
|
* indexing to grok it correctly. Make such changes here.
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $string String
|
|
|
|
|
|
* @return String
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
*/
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function stripForSearch( $string ) {
|
2007-01-03 16:36:05 +00:00
|
|
|
|
global $wgDBtype;
|
|
|
|
|
|
if ( $wgDBtype != 'mysql' ) {
|
|
|
|
|
|
return $string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
2008-11-25 02:39:06 +00:00
|
|
|
|
|
|
|
|
|
|
// MySQL fulltext index doesn't grok utf-8, so we
|
|
|
|
|
|
// need to fold cases and convert to hex
|
|
|
|
|
|
$out = preg_replace_callback(
|
|
|
|
|
|
"/([\\xc0-\\xff][\\x80-\\xbf]*)/",
|
|
|
|
|
|
array( $this, 'stripForSearchCallback' ),
|
|
|
|
|
|
$this->lc( $string ) );
|
|
|
|
|
|
|
|
|
|
|
|
// And to add insult to injury, the default indexing
|
|
|
|
|
|
// ignores short words... Pad them so we can pass them
|
|
|
|
|
|
// through without reconfiguring the server...
|
|
|
|
|
|
$minLength = $this->minSearchLength();
|
|
|
|
|
|
if( $minLength > 1 ) {
|
|
|
|
|
|
$n = $minLength-1;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$out = preg_replace(
|
2008-11-25 02:39:06 +00:00
|
|
|
|
"/\b(\w{1,$n})\b/",
|
|
|
|
|
|
"$1U800",
|
|
|
|
|
|
$out );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
2008-11-25 02:39:06 +00:00
|
|
|
|
|
2008-12-19 01:50:07 +00:00
|
|
|
|
// Periods within things like hostnames and IP addresses
|
|
|
|
|
|
// are also important -- we want a search for "example.com"
|
|
|
|
|
|
// or "192.168.1.1" to work sanely.
|
|
|
|
|
|
//
|
|
|
|
|
|
// MySQL's search seems to ignore them, so you'd match on
|
|
|
|
|
|
// "example.wikipedia.com" and "192.168.83.1" as well.
|
|
|
|
|
|
$out = preg_replace(
|
|
|
|
|
|
"/(\w)\.(\w|\*)/u",
|
|
|
|
|
|
"$1U82e$2",
|
|
|
|
|
|
$out );
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
|
return $out;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2008-11-25 02:39:06 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Armor a case-folded UTF-8 string to get through MySQL's
|
|
|
|
|
|
* fulltext search without being mucked up by funny charset
|
|
|
|
|
|
* settings or anything else of the sort.
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected function stripForSearchCallback( $matches ) {
|
|
|
|
|
|
return 'U8' . bin2hex( $matches[1] );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Check MySQL server's ft_min_word_len setting so we know
|
|
|
|
|
|
* if we need to pad short words...
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected function minSearchLength() {
|
|
|
|
|
|
if( !isset( $this->minSearchLength ) ) {
|
|
|
|
|
|
$sql = "show global variables like 'ft\\_min\\_word\\_len'";
|
|
|
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
|
|
|
|
|
$result = $dbr->query( $sql );
|
|
|
|
|
|
$row = $result->fetchObject();
|
|
|
|
|
|
$result->free();
|
|
|
|
|
|
|
|
|
|
|
|
if( $row && $row->Variable_name == 'ft_min_word_len' ) {
|
|
|
|
|
|
$this->minSearchLength = intval( $row->Value );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$this->minSearchLength = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return $this->minSearchLength;
|
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2004-11-29 01:22:44 +00:00
|
|
|
|
function convertForSearchResult( $termsArray ) {
|
|
|
|
|
|
# some languages, e.g. Chinese, need to do a conversion
|
|
|
|
|
|
# in order for search results to be displayed correctly
|
|
|
|
|
|
return $termsArray;
|
2005-07-03 07:15:53 +00:00
|
|
|
|
}
|
2004-11-29 01:22:44 +00:00
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
2006-07-26 07:15:39 +00:00
|
|
|
|
* Get the first character of a string.
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $s string
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2004-06-05 08:31:41 +00:00
|
|
|
|
function firstChar( $s ) {
|
2007-01-12 07:26:32 +00:00
|
|
|
|
$matches = array();
|
2006-07-26 07:15:39 +00:00
|
|
|
|
preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
|
|
|
|
|
|
'[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})/', $s, $matches);
|
|
|
|
|
|
|
2008-05-19 20:20:33 +00:00
|
|
|
|
if ( isset( $matches[1] ) ) {
|
|
|
|
|
|
if ( strlen( $matches[1] ) != 3 ) {
|
|
|
|
|
|
return $matches[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Break down Hangul syllables to grab the first jamo
|
|
|
|
|
|
$code = utf8ToCodepoint( $matches[1] );
|
|
|
|
|
|
if ( $code < 0xac00 || 0xd7a4 <= $code) {
|
|
|
|
|
|
return $matches[1];
|
|
|
|
|
|
} elseif ( $code < 0xb098 ) {
|
|
|
|
|
|
return "\xe3\x84\xb1";
|
|
|
|
|
|
} elseif ( $code < 0xb2e4 ) {
|
|
|
|
|
|
return "\xe3\x84\xb4";
|
|
|
|
|
|
} elseif ( $code < 0xb77c ) {
|
|
|
|
|
|
return "\xe3\x84\xb7";
|
|
|
|
|
|
} elseif ( $code < 0xb9c8 ) {
|
|
|
|
|
|
return "\xe3\x84\xb9";
|
|
|
|
|
|
} elseif ( $code < 0xbc14 ) {
|
|
|
|
|
|
return "\xe3\x85\x81";
|
|
|
|
|
|
} elseif ( $code < 0xc0ac ) {
|
|
|
|
|
|
return "\xe3\x85\x82";
|
|
|
|
|
|
} elseif ( $code < 0xc544 ) {
|
|
|
|
|
|
return "\xe3\x85\x85";
|
|
|
|
|
|
} elseif ( $code < 0xc790 ) {
|
|
|
|
|
|
return "\xe3\x85\x87";
|
|
|
|
|
|
} elseif ( $code < 0xcc28 ) {
|
|
|
|
|
|
return "\xe3\x85\x88";
|
|
|
|
|
|
} elseif ( $code < 0xce74 ) {
|
|
|
|
|
|
return "\xe3\x85\x8a";
|
|
|
|
|
|
} elseif ( $code < 0xd0c0 ) {
|
|
|
|
|
|
return "\xe3\x85\x8b";
|
|
|
|
|
|
} elseif ( $code < 0xd30c ) {
|
|
|
|
|
|
return "\xe3\x85\x8c";
|
|
|
|
|
|
} elseif ( $code < 0xd558 ) {
|
|
|
|
|
|
return "\xe3\x85\x8d";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return "\xe3\x85\x8e";
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
2004-06-05 08:31:41 +00:00
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2005-03-14 02:00:53 +00:00
|
|
|
|
function initEncoding() {
|
|
|
|
|
|
# Some languages may have an alternate char encoding option
|
|
|
|
|
|
# (Esperanto X-coding, Japanese furigana conversion, etc)
|
|
|
|
|
|
# If this language is used as the primary content language,
|
|
|
|
|
|
# an override to the defaults can be set here on startup.
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function recodeForEdit( $s ) {
|
|
|
|
|
|
# For some languages we'll want to explicitly specify
|
|
|
|
|
|
# which characters make it into the edit box raw
|
|
|
|
|
|
# or are converted in some way or another.
|
|
|
|
|
|
# Note that if wgOutputEncoding is different from
|
|
|
|
|
|
# wgInputEncoding, this text will be further converted
|
|
|
|
|
|
# to wgOutputEncoding.
|
2006-07-26 07:15:39 +00:00
|
|
|
|
global $wgEditEncoding;
|
2004-06-08 19:23:19 +00:00
|
|
|
|
if( $wgEditEncoding == '' or
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$wgEditEncoding == 'UTF-8' ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
|
return $s;
|
|
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->iconv( 'UTF-8', $wgEditEncoding, $s );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function recodeInput( $s ) {
|
|
|
|
|
|
# Take the previous into account.
|
2006-07-26 07:15:39 +00:00
|
|
|
|
global $wgEditEncoding;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
if($wgEditEncoding != "") {
|
|
|
|
|
|
$enc = $wgEditEncoding;
|
|
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$enc = 'UTF-8';
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if( $enc == 'UTF-8' ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
|
return $s;
|
|
|
|
|
|
} else {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->iconv( $enc, 'UTF-8', $s );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* For right-to-left language support
|
2005-05-03 12:27:30 +00:00
|
|
|
|
*
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
* @return bool
|
|
|
|
|
|
*/
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function isRTL() {
|
|
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->rtl;
|
|
|
|
|
|
}
|
2006-06-20 08:11:56 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* A hidden direction mark (LRM or RLM), depending on the language direction
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2006-08-06 18:08:21 +00:00
|
|
|
|
function getDirMark() {
|
|
|
|
|
|
return $this->isRTL() ? "\xE2\x80\x8F" : "\xE2\x80\x8E";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* An arrow, depending on the language direction
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getArrow() {
|
|
|
|
|
|
return $this->isRTL() ? '←' : '→';
|
|
|
|
|
|
}
|
2003-08-31 09:46:37 +00:00
|
|
|
|
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* To allow "foo[[bar]]" to extend the link over the whole word "foobar"
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return bool
|
|
|
|
|
|
*/
|
2006-08-06 18:08:21 +00:00
|
|
|
|
function linkPrefixExtension() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
2006-08-06 18:08:21 +00:00
|
|
|
|
return $this->linkPrefixExtension;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
2004-02-15 10:05:52 +00:00
|
|
|
|
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function &getMagicWords() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->magicWords;
|
2003-08-31 09:46:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Fill a MagicWord object with data from here
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function getMagic( &$mw ) {
|
2007-09-04 02:48:34 +00:00
|
|
|
|
if ( !$this->mMagicHookDone ) {
|
|
|
|
|
|
$this->mMagicHookDone = true;
|
2006-07-03 03:30:28 +00:00
|
|
|
|
wfRunHooks( 'LanguageGetMagic', array( &$this->mMagicExtensions, $this->getCode() ) );
|
2004-05-28 21:20:51 +00:00
|
|
|
|
}
|
2006-07-03 03:30:28 +00:00
|
|
|
|
if ( isset( $this->mMagicExtensions[$mw->mId] ) ) {
|
|
|
|
|
|
$rawEntry = $this->mMagicExtensions[$mw->mId];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$magicWords =& $this->getMagicWords();
|
|
|
|
|
|
if ( isset( $magicWords[$mw->mId] ) ) {
|
|
|
|
|
|
$rawEntry = $magicWords[$mw->mId];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
# Fall back to English if local list is incomplete
|
|
|
|
|
|
$magicWords =& Language::getMagicWords();
|
2008-08-18 03:30:36 +00:00
|
|
|
|
if ( !isset($magicWords[$mw->mId]) ) {
|
|
|
|
|
|
throw new MWException("Magic word '{$mw->mId}' not found" );
|
|
|
|
|
|
}
|
2006-07-03 03:30:28 +00:00
|
|
|
|
$rawEntry = $magicWords[$mw->mId];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-08-31 10:19:12 +00:00
|
|
|
|
if( !is_array( $rawEntry ) ) {
|
|
|
|
|
|
error_log( "\"$rawEntry\" is not a valid magic thingie for \"$mw->mId\"" );
|
2007-12-06 22:16:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
$mw->mCaseSensitive = $rawEntry[0];
|
|
|
|
|
|
$mw->mSynonyms = array_slice( $rawEntry, 1 );
|
2006-08-31 10:19:12 +00:00
|
|
|
|
}
|
2003-08-31 09:46:37 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2007-09-04 02:48:34 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Add magic words to the extension array
|
|
|
|
|
|
*/
|
|
|
|
|
|
function addMagicWordsByLang( $newWords ) {
|
|
|
|
|
|
$code = $this->getCode();
|
|
|
|
|
|
$fallbackChain = array();
|
|
|
|
|
|
while ( $code && !in_array( $code, $fallbackChain ) ) {
|
|
|
|
|
|
$fallbackChain[] = $code;
|
|
|
|
|
|
$code = self::getFallbackFor( $code );
|
|
|
|
|
|
}
|
2007-09-06 00:21:49 +00:00
|
|
|
|
if ( !in_array( 'en', $fallbackChain ) ) {
|
|
|
|
|
|
$fallbackChain[] = 'en';
|
|
|
|
|
|
}
|
2007-09-04 02:48:34 +00:00
|
|
|
|
$fallbackChain = array_reverse( $fallbackChain );
|
|
|
|
|
|
foreach ( $fallbackChain as $code ) {
|
|
|
|
|
|
if ( isset( $newWords[$code] ) ) {
|
|
|
|
|
|
$this->mMagicExtensions = $newWords[$code] + $this->mMagicExtensions;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-10-30 06:25:31 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Get special page names, as an associative array
|
|
|
|
|
|
* case folded alias => real name
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getSpecialPageAliases() {
|
|
|
|
|
|
$this->load();
|
2008-06-25 10:59:22 +00:00
|
|
|
|
|
|
|
|
|
|
// Cache aliases because it may be slow to load them
|
2006-10-30 06:25:31 +00:00
|
|
|
|
if ( !isset( $this->mExtendedSpecialPageAliases ) ) {
|
2008-06-25 10:59:22 +00:00
|
|
|
|
|
|
|
|
|
|
// Initialise array
|
2006-10-30 06:25:31 +00:00
|
|
|
|
$this->mExtendedSpecialPageAliases = $this->specialPageAliases;
|
2008-06-25 10:59:22 +00:00
|
|
|
|
|
|
|
|
|
|
global $wgExtensionAliasesFiles;
|
|
|
|
|
|
foreach ( $wgExtensionAliasesFiles as $file ) {
|
|
|
|
|
|
|
|
|
|
|
|
// Fail fast
|
|
|
|
|
|
if ( !file_exists($file) )
|
2008-08-12 10:14:09 +00:00
|
|
|
|
throw new MWException( "Aliases file does not exist: $file" );
|
2008-06-25 10:59:22 +00:00
|
|
|
|
|
|
|
|
|
|
$aliases = array();
|
|
|
|
|
|
require($file);
|
|
|
|
|
|
|
|
|
|
|
|
// Check the availability of aliases
|
|
|
|
|
|
if ( !isset($aliases['en']) )
|
2008-08-12 10:14:09 +00:00
|
|
|
|
throw new MWException( "Malformed aliases file: $file" );
|
2008-06-25 10:59:22 +00:00
|
|
|
|
|
2008-06-25 11:23:34 +00:00
|
|
|
|
// Merge all aliases in fallback chain
|
2008-06-25 10:59:22 +00:00
|
|
|
|
$code = $this->getCode();
|
2008-06-25 11:23:34 +00:00
|
|
|
|
do {
|
|
|
|
|
|
if ( !isset($aliases[$code]) ) continue;
|
2008-06-25 10:59:22 +00:00
|
|
|
|
|
|
|
|
|
|
$aliases[$code] = $this->fixSpecialPageAliases( $aliases[$code] );
|
|
|
|
|
|
/* Merge the aliases, THIS will break if there is special page name
|
|
|
|
|
|
* which looks like a numerical key, thanks to PHP...
|
2008-11-01 23:20:25 +00:00
|
|
|
|
* See the array_merge_recursive manual entry */
|
2008-06-25 10:59:22 +00:00
|
|
|
|
$this->mExtendedSpecialPageAliases = array_merge_recursive(
|
|
|
|
|
|
$this->mExtendedSpecialPageAliases, $aliases[$code] );
|
|
|
|
|
|
|
2008-06-25 11:23:34 +00:00
|
|
|
|
} while ( $code = self::getFallbackFor( $code ) );
|
2008-06-25 10:59:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wfRunHooks( 'LanguageGetSpecialPageAliases',
|
2008-06-25 15:14:41 +00:00
|
|
|
|
array( &$this->mExtendedSpecialPageAliases, $this->getCode() ) );
|
2006-10-30 06:25:31 +00:00
|
|
|
|
}
|
2008-06-25 10:59:22 +00:00
|
|
|
|
|
2006-10-30 06:25:31 +00:00
|
|
|
|
return $this->mExtendedSpecialPageAliases;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2008-06-25 10:59:22 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Function to fix special page aliases. Will convert the first letter to
|
|
|
|
|
|
* upper case and spaces to underscores. Can be given a full aliases array,
|
|
|
|
|
|
* in which case it will recursively fix all aliases.
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function fixSpecialPageAliases( $mixed ) {
|
|
|
|
|
|
// Work recursively until in string level
|
|
|
|
|
|
if ( is_array($mixed) ) {
|
|
|
|
|
|
$callback = array( $this, 'fixSpecialPageAliases' );
|
|
|
|
|
|
return array_map( $callback, $mixed );
|
|
|
|
|
|
}
|
|
|
|
|
|
return str_replace( ' ', '_', $this->ucfirst( $mixed ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-07-03 07:15:53 +00:00
|
|
|
|
/**
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
* Italic is unsuitable for some languages
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $text String: the text to be emphasized.
|
2005-05-03 12:27:30 +00:00
|
|
|
|
* @return string
|
* @package MediaWiki and @subpackage Language
* Documented getDefaultUserOptions(), getBookstoreList(), getNsText(),
getNsIndex(), getVariantname(), stripForSearch(), firstChar(), isRTL(),
linkPrefixExtension(), emphasize(), formatNum()
2005-04-05 11:12:30 +00:00
|
|
|
|
*/
|
2004-11-21 07:36:46 +00:00
|
|
|
|
function emphasize( $text ) {
|
2005-05-03 12:27:30 +00:00
|
|
|
|
return "<em>$text</em>";
|
2004-01-30 14:50:26 +00:00
|
|
|
|
}
|
2004-03-02 20:23:56 +00:00
|
|
|
|
|
2006-04-29 20:07:14 +00:00
|
|
|
|
/**
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* Normally we output all numbers in plain en_US style, that is
|
|
|
|
|
|
* 293,291.235 for twohundredninetythreethousand-twohundredninetyone
|
|
|
|
|
|
* point twohundredthirtyfive. However this is not sutable for all
|
|
|
|
|
|
* languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
|
|
|
|
|
|
* Icelandic just want to use commas instead of dots, and dots instead
|
|
|
|
|
|
* of commas like "293.291,235".
|
|
|
|
|
|
*
|
|
|
|
|
|
* An example of this function being called:
|
|
|
|
|
|
* <code>
|
|
|
|
|
|
* wfMsg( 'message', $wgLang->formatNum( $num ) )
|
|
|
|
|
|
* </code>
|
|
|
|
|
|
*
|
|
|
|
|
|
* See LanguageGu.php for the Gujarati implementation and
|
2008-10-17 20:06:37 +00:00
|
|
|
|
* $separatorTransformTable on MessageIs.php for
|
|
|
|
|
|
* the , => . and . => , implementation.
|
2008-05-21 18:18:58 +00:00
|
|
|
|
*
|
|
|
|
|
|
* @todo check if it's viable to use localeconv() for the decimal
|
2008-09-15 20:38:27 +00:00
|
|
|
|
* separator thing.
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $number Mixed: the string to be formatted, should be an integer
|
|
|
|
|
|
* or a floating point number.
|
|
|
|
|
|
* @param $nocommafy Bool: set to true for special numbers like dates
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2006-04-29 21:44:57 +00:00
|
|
|
|
function formatNum( $number, $nocommafy = false ) {
|
2006-04-29 20:07:14 +00:00
|
|
|
|
global $wgTranslateNumerals;
|
2006-04-29 21:44:57 +00:00
|
|
|
|
if (!$nocommafy) {
|
2006-04-29 20:07:14 +00:00
|
|
|
|
$number = $this->commafy($number);
|
|
|
|
|
|
$s = $this->separatorTransformTable();
|
2008-12-24 15:05:44 +00:00
|
|
|
|
if ($s) { $number = strtr($number, $s); }
|
2006-04-29 20:07:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($wgTranslateNumerals) {
|
|
|
|
|
|
$s = $this->digitTransformTable();
|
2008-12-24 15:05:44 +00:00
|
|
|
|
if ($s) { $number = strtr($number, $s); }
|
2006-04-29 20:07:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $number;
|
2004-03-06 03:03:14 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2006-12-23 18:58:44 +00:00
|
|
|
|
function parseFormattedNumber( $number ) {
|
|
|
|
|
|
$s = $this->digitTransformTable();
|
2008-12-24 15:05:44 +00:00
|
|
|
|
if ($s) { $number = strtr($number, array_flip($s)); }
|
2006-12-23 18:58:44 +00:00
|
|
|
|
|
|
|
|
|
|
$s = $this->separatorTransformTable();
|
2008-12-24 15:05:44 +00:00
|
|
|
|
if ($s) { $number = strtr($number, array_flip($s)); }
|
2006-12-23 18:58:44 +00:00
|
|
|
|
|
|
|
|
|
|
$number = strtr( $number, array (',' => '') );
|
|
|
|
|
|
return $number;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-04-12 23:21:59 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Adds commas to a given number
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $_ mixed
|
2005-04-12 23:21:59 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
|
|
|
|
|
function commafy($_) {
|
|
|
|
|
|
return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
|
|
|
|
|
|
}
|
2005-04-13 08:37:03 +00:00
|
|
|
|
|
2006-04-29 20:07:14 +00:00
|
|
|
|
function digitTransformTable() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->digitTransformTable;
|
2006-04-29 20:07:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function separatorTransformTable() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->separatorTransformTable;
|
2006-04-29 20:07:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-04-13 08:37:03 +00:00
|
|
|
|
/**
|
2008-12-27 19:58:11 +00:00
|
|
|
|
* Take a list of strings and build a locale-friendly comma-separated
|
|
|
|
|
|
* list, using the local comma-separator message.
|
|
|
|
|
|
* The last two strings are chained with an "and".
|
2005-04-13 08:37:03 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $l Array
|
2005-04-13 08:37:03 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2004-08-01 20:43:54 +00:00
|
|
|
|
function listToText( $l ) {
|
|
|
|
|
|
$s = '';
|
2008-12-27 19:58:11 +00:00
|
|
|
|
$m = count( $l ) - 1;
|
|
|
|
|
|
if( $m == 1 ) {
|
|
|
|
|
|
return $l[0] . $this->getMessageFromDB( 'and' ) . $this->getMessageFromDB( 'word-separator' ) . $l[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
for ( $i = $m; $i >= 0; $i-- ) {
|
|
|
|
|
|
if ( $i == $m ) {
|
|
|
|
|
|
$s = $l[$i];
|
|
|
|
|
|
} else if( $i == $m - 1 ) {
|
|
|
|
|
|
$s = $l[$i] . $this->getMessageFromDB( 'and' ) . $this->getMessageFromDB( 'word-separator' ) . $s;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$s = $l[$i] . $this->getMessageFromDB( 'comma-separator' ) . $s;
|
|
|
|
|
|
}
|
2004-08-01 20:43:54 +00:00
|
|
|
|
}
|
2008-12-27 19:58:11 +00:00
|
|
|
|
return $s;
|
2004-08-01 20:43:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2008-12-27 19:58:11 +00:00
|
|
|
|
|
2008-09-19 18:47:47 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Take a list of strings and build a locale-friendly comma-separated
|
|
|
|
|
|
* list, using the local comma-separator message.
|
2008-09-30 16:24:23 +00:00
|
|
|
|
* @param $list array of strings to put in a comma list
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
|
|
|
|
|
function commaList( $list, $forContent = false ) {
|
|
|
|
|
|
return implode(
|
|
|
|
|
|
$list,
|
2008-09-30 17:15:11 +00:00
|
|
|
|
wfMsgExt( 'comma-separator', array( 'escapenoentities', 'language' => $this ) ) );
|
2008-09-30 16:24:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Same as commaList, but separate it with the pipe instead.
|
|
|
|
|
|
* @param $list array of strings to put in a pipe list
|
|
|
|
|
|
* @return string
|
2008-09-19 18:47:47 +00:00
|
|
|
|
*/
|
2008-09-30 17:15:11 +00:00
|
|
|
|
function pipeList( $list ) {
|
2008-09-19 18:47:47 +00:00
|
|
|
|
return implode(
|
|
|
|
|
|
$list,
|
2008-09-30 17:15:11 +00:00
|
|
|
|
wfMsgExt( 'pipe-separator', array( 'escapenoentities', 'language' => $this ) ) );
|
2008-09-19 18:47:47 +00:00
|
|
|
|
}
|
2004-08-09 05:38:11 +00:00
|
|
|
|
|
2007-08-29 01:34:44 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Truncate a string to a specified length in bytes, appending an optional
|
|
|
|
|
|
* string (e.g. for ellipses)
|
|
|
|
|
|
*
|
|
|
|
|
|
* The database offers limited byte lengths for some columns in the database;
|
|
|
|
|
|
* multi-byte character sets mean we need to ensure that only whole characters
|
|
|
|
|
|
* are included, otherwise broken characters can be passed to the user
|
|
|
|
|
|
*
|
|
|
|
|
|
* If $length is negative, the string will be truncated from the beginning
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $string String to truncate
|
|
|
|
|
|
* @param $length Int: maximum length (excluding ellipses)
|
|
|
|
|
|
* @param $ellipsis String to append to the truncated text
|
2007-08-29 01:34:44 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function truncate( $string, $length, $ellipsis = "" ) {
|
2004-08-01 20:43:54 +00:00
|
|
|
|
if( $length == 0 ) {
|
|
|
|
|
|
return $ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( strlen( $string ) <= abs( $length ) ) {
|
|
|
|
|
|
return $string;
|
|
|
|
|
|
}
|
|
|
|
|
|
if( $length > 0 ) {
|
|
|
|
|
|
$string = substr( $string, 0, $length );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$char = ord( $string[strlen( $string ) - 1] );
|
2007-01-12 07:26:32 +00:00
|
|
|
|
$m = array();
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ($char >= 0xc0) {
|
|
|
|
|
|
# We got the first byte only of a multibyte char; remove it.
|
|
|
|
|
|
$string = substr( $string, 0, -1 );
|
|
|
|
|
|
} elseif( $char >= 0x80 &&
|
|
|
|
|
|
preg_match( '/^(.*)(?:[\xe0-\xef][\x80-\xbf]|' .
|
|
|
|
|
|
'[\xf0-\xf7][\x80-\xbf]{1,2})$/', $string, $m ) ) {
|
|
|
|
|
|
# We chopped in the middle of a character; remove it
|
|
|
|
|
|
$string = $m[1];
|
|
|
|
|
|
}
|
2004-08-01 20:43:54 +00:00
|
|
|
|
return $string . $ellipsis;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$string = substr( $string, $length );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$char = ord( $string[0] );
|
|
|
|
|
|
if( $char >= 0x80 && $char < 0xc0 ) {
|
|
|
|
|
|
# We chopped in the middle of a character; remove the whole thing
|
|
|
|
|
|
$string = preg_replace( '/^[\x80-\xbf]+/', '', $string );
|
|
|
|
|
|
}
|
2004-08-01 20:43:54 +00:00
|
|
|
|
return $ellipsis . $string;
|
2004-04-26 05:14:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2004-08-27 14:55:41 +00:00
|
|
|
|
|
2005-04-13 08:37:03 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Grammatical transformations, needed for inflected languages
|
|
|
|
|
|
* Invoked by putting {{grammar:case|word}} in a message
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $word string
|
|
|
|
|
|
* @param $case string
|
2005-04-13 08:37:03 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
2004-08-27 14:55:41 +00:00
|
|
|
|
function convertGrammar( $word, $case ) {
|
2006-05-25 14:21:45 +00:00
|
|
|
|
global $wgGrammarForms;
|
2008-01-02 19:58:15 +00:00
|
|
|
|
if ( isset($wgGrammarForms[$this->getCode()][$case][$word]) ) {
|
|
|
|
|
|
return $wgGrammarForms[$this->getCode()][$case][$word];
|
2006-05-25 14:21:45 +00:00
|
|
|
|
}
|
2004-08-27 14:55:41 +00:00
|
|
|
|
return $word;
|
|
|
|
|
|
}
|
2004-09-17 05:51:03 +00:00
|
|
|
|
|
2005-09-05 19:22:09 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Plural form transformations, needed for some languages.
|
2007-10-15 10:32:54 +00:00
|
|
|
|
* For example, there are 3 form of plural in Russian and Polish,
|
2005-09-05 19:22:09 +00:00
|
|
|
|
* depending on "count mod 10". See [[w:Plural]]
|
|
|
|
|
|
* For English it is pretty simple.
|
|
|
|
|
|
*
|
2005-09-06 17:02:19 +00:00
|
|
|
|
* Invoked by putting {{plural:count|wordform1|wordform2}}
|
|
|
|
|
|
* or {{plural:count|wordform1|wordform2|wordform3}}
|
2005-09-05 19:22:09 +00:00
|
|
|
|
*
|
2006-01-07 13:09:30 +00:00
|
|
|
|
* Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
|
2005-09-05 19:22:09 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $count Integer: non-localized number
|
|
|
|
|
|
* @param $forms Array: different plural forms
|
2007-11-18 20:15:49 +00:00
|
|
|
|
* @return string Correct form of plural for $count in this language
|
|
|
|
|
|
*/
|
|
|
|
|
|
function convertPlural( $count, $forms ) {
|
|
|
|
|
|
if ( !count($forms) ) { return ''; }
|
|
|
|
|
|
$forms = $this->preConvertPlural( $forms, 2 );
|
|
|
|
|
|
|
2008-09-03 03:54:38 +00:00
|
|
|
|
return ( $count == 1 ) ? $forms[0] : $forms[1];
|
2007-11-18 20:15:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Checks that convertPlural was given an array and pads it to requested
|
|
|
|
|
|
* amound of forms by copying the last one.
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $count Integer: How many forms should there be at least
|
|
|
|
|
|
* @param $forms Array of forms given to convertPlural
|
2007-11-18 20:15:49 +00:00
|
|
|
|
* @return array Padded array of forms or an exception if not an array
|
2005-09-05 19:22:09 +00:00
|
|
|
|
*/
|
2007-12-22 12:41:42 +00:00
|
|
|
|
protected function preConvertPlural( /* Array */ $forms, $count ) {
|
2007-11-18 20:15:49 +00:00
|
|
|
|
while ( count($forms) < $count ) {
|
|
|
|
|
|
$forms[] = $forms[count($forms)-1];
|
|
|
|
|
|
}
|
|
|
|
|
|
return $forms;
|
2005-09-05 19:22:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2005-08-27 16:35:10 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* For translaing of expiry times
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $str String: the validated block time in English
|
2005-08-27 16:35:10 +00:00
|
|
|
|
* @return Somehow translated block time
|
|
|
|
|
|
* @see LanguageFi.php for example implementation
|
|
|
|
|
|
*/
|
2007-09-10 01:53:24 +00:00
|
|
|
|
function translateBlockExpiry( $str ) {
|
2006-01-03 20:59:19 +00:00
|
|
|
|
|
2006-08-06 18:32:12 +00:00
|
|
|
|
$scBlockExpiryOptions = $this->getMessageFromDB( 'ipboptions' );
|
2006-01-03 20:59:19 +00:00
|
|
|
|
|
|
|
|
|
|
if ( $scBlockExpiryOptions == '-') {
|
|
|
|
|
|
return $str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (explode(',', $scBlockExpiryOptions) as $option) {
|
|
|
|
|
|
if ( strpos($option, ":") === false )
|
|
|
|
|
|
continue;
|
|
|
|
|
|
list($show, $value) = explode(":", $option);
|
2007-02-16 20:48:33 +00:00
|
|
|
|
if ( strcmp ( $str, $value) == 0 ) {
|
2007-09-10 01:53:24 +00:00
|
|
|
|
return htmlspecialchars( trim( $show ) );
|
2007-02-16 20:48:33 +00:00
|
|
|
|
}
|
2006-01-03 20:59:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2005-08-27 16:35:10 +00:00
|
|
|
|
return $str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-04-13 08:37:03 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* languages like Chinese need to be segmented in order for the diff
|
|
|
|
|
|
* to be of any use
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $text String
|
|
|
|
|
|
* @return String
|
2005-04-13 08:37:03 +00:00
|
|
|
|
*/
|
2004-12-05 02:17:21 +00:00
|
|
|
|
function segmentForDiff( $text ) {
|
|
|
|
|
|
return $text;
|
|
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2005-04-13 08:37:03 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* and unsegment to show the result
|
|
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $text String
|
|
|
|
|
|
* @return String
|
2005-04-13 08:37:03 +00:00
|
|
|
|
*/
|
2004-12-05 02:17:21 +00:00
|
|
|
|
function unsegmentForDiff( $text ) {
|
|
|
|
|
|
return $text;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2004-12-24 02:47:38 +00:00
|
|
|
|
# convert text to different variants of a language.
|
2005-05-03 12:27:30 +00:00
|
|
|
|
function convert( $text, $isTitle = false) {
|
2005-04-15 14:12:39 +00:00
|
|
|
|
return $this->mConverter->convert($text, $isTitle);
|
2004-10-19 18:02:44 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2006-03-01 01:57:53 +00:00
|
|
|
|
# Convert text from within Parser
|
|
|
|
|
|
function parserConvert( $text, &$parser ) {
|
|
|
|
|
|
return $this->mConverter->parserConvert( $text, $parser );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-20 10:22:12 +00:00
|
|
|
|
# Check if this is a language with variants
|
|
|
|
|
|
function hasVariants(){
|
|
|
|
|
|
return sizeof($this->getVariants())>1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-12-11 23:33:27 +00:00
|
|
|
|
# Put custom tags (e.g. -{ }-) around math to prevent conversion
|
|
|
|
|
|
function armourMath($text){
|
|
|
|
|
|
return $this->mConverter->armourMath($text);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-20 10:22:12 +00:00
|
|
|
|
|
2005-06-28 19:56:17 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Perform output conversion on a string, and encode for safe HTML output.
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $text String
|
|
|
|
|
|
* @param $isTitle Bool -- wtf?
|
2005-06-28 19:56:17 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
* @todo this should get integrated somewhere sane
|
|
|
|
|
|
*/
|
|
|
|
|
|
function convertHtml( $text, $isTitle = false ) {
|
|
|
|
|
|
return htmlspecialchars( $this->convert( $text, $isTitle ) );
|
|
|
|
|
|
}
|
2004-10-19 18:02:44 +00:00
|
|
|
|
|
2005-04-28 03:33:54 +00:00
|
|
|
|
function convertCategoryKey( $key ) {
|
|
|
|
|
|
return $this->mConverter->convertCategoryKey( $key );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-04-08 16:31:32 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* get the list of variants supported by this langauge
|
|
|
|
|
|
* see sample implementation in LanguageZh.php
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return array an array of language codes
|
|
|
|
|
|
*/
|
2004-09-24 18:37:33 +00:00
|
|
|
|
function getVariants() {
|
2005-04-15 14:12:39 +00:00
|
|
|
|
return $this->mConverter->getVariants();
|
2004-09-24 18:37:33 +00:00
|
|
|
|
}
|
2005-04-08 16:31:32 +00:00
|
|
|
|
|
2004-10-08 13:57:01 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function getPreferredVariant( $fromUser = true ) {
|
|
|
|
|
|
return $this->mConverter->getPreferredVariant( $fromUser );
|
2004-09-24 18:37:33 +00:00
|
|
|
|
}
|
2004-10-21 02:47:51 +00:00
|
|
|
|
|
2005-04-08 16:31:32 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* if a language supports multiple variants, it is
|
2005-04-07 21:59:02 +00:00
|
|
|
|
* possible that non-existing link in one variant
|
2005-07-03 07:15:53 +00:00
|
|
|
|
* actually exists in another variant. this function
|
2005-04-07 21:59:02 +00:00
|
|
|
|
* tries to find it. See e.g. LanguageZh.php
|
2005-04-08 16:31:32 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $link String: the name of the link
|
|
|
|
|
|
* @param $nt Mixed: the title object of the link
|
2005-04-08 16:31:32 +00:00
|
|
|
|
* @return null the input parameters may be modified upon return
|
2005-04-07 21:59:02 +00:00
|
|
|
|
*/
|
2008-08-25 18:06:54 +00:00
|
|
|
|
function findVariantLink( &$link, &$nt, $forTemplate = false ) {
|
|
|
|
|
|
$this->mConverter->findVariantLink($link, $nt, $forTemplate );
|
2004-10-21 02:47:51 +00:00
|
|
|
|
}
|
2004-12-07 22:23:21 +00:00
|
|
|
|
|
2006-09-20 10:22:12 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* If a language supports multiple variants, converts text
|
|
|
|
|
|
* into an array of all possible variants of the text:
|
|
|
|
|
|
* 'variant' => text in that variant
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
function convertLinkToAllVariants($text){
|
|
|
|
|
|
return $this->mConverter->convertLinkToAllVariants($text);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-04-08 16:31:32 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* returns language specific options used by User::getPageRenderHash()
|
|
|
|
|
|
* for example, the preferred language variant
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return string
|
2005-04-07 21:59:02 +00:00
|
|
|
|
*/
|
2004-12-07 22:23:21 +00:00
|
|
|
|
function getExtraHashOptions() {
|
2005-04-15 14:12:39 +00:00
|
|
|
|
return $this->mConverter->getExtraHashOptions();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* for languages that support multiple variants, the title of an
|
|
|
|
|
|
* article may be displayed differently in different variants. this
|
|
|
|
|
|
* function returns the apporiate title defined in the body of the article.
|
2005-07-03 07:15:53 +00:00
|
|
|
|
*
|
2005-04-15 14:12:39 +00:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getParsedTitle() {
|
|
|
|
|
|
return $this->mConverter->getParsedTitle();
|
2004-12-07 22:23:21 +00:00
|
|
|
|
}
|
2005-07-03 07:15:53 +00:00
|
|
|
|
|
2005-04-15 14:12:39 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Enclose a string with the "no conversion" tag. This is used by
|
|
|
|
|
|
* various functions in the Parser
|
2005-07-03 07:15:53 +00:00
|
|
|
|
*
|
2008-05-21 18:18:58 +00:00
|
|
|
|
* @param $text String: text to be tagged for no conversion
|
|
|
|
|
|
* @param $noParse
|
2005-04-15 14:12:39 +00:00
|
|
|
|
* @return string the tagged text
|
2008-05-21 18:18:58 +00:00
|
|
|
|
*/
|
2006-09-20 10:22:12 +00:00
|
|
|
|
function markNoConversion( $text, $noParse=false ) {
|
|
|
|
|
|
return $this->mConverter->markNoConversion( $text, $noParse );
|
2005-04-15 14:12:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2004-12-09 05:51:20 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* A regular expression to match legal word-trailing characters
|
|
|
|
|
|
* which should be merged onto a link of the form [[foo]]bar.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
|
|
|
|
|
function linkTrail() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$this->load();
|
|
|
|
|
|
return $this->linkTrail;
|
2004-12-09 05:51:20 +00:00
|
|
|
|
}
|
2004-12-07 22:23:21 +00:00
|
|
|
|
|
2004-12-24 02:47:38 +00:00
|
|
|
|
function getLangObj() {
|
|
|
|
|
|
return $this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-07-06 07:53:51 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Get the RFC 3066 code for this language object
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getCode() {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
return $this->mCode;
|
2005-07-06 07:53:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
function setCode( $code ) {
|
|
|
|
|
|
$this->mCode = $code;
|
|
|
|
|
|
}
|
2005-04-07 23:04:08 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) {
|
|
|
|
|
|
return $prefix . str_replace( '-', '_', ucfirst( $code ) ) . $suffix;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-10-04 01:39:28 +00:00
|
|
|
|
static function getMessagesFileName( $code ) {
|
|
|
|
|
|
global $IP;
|
|
|
|
|
|
return self::getFileName( "$IP/languages/messages/Messages", $code, '.php' );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static function getClassFileName( $code ) {
|
|
|
|
|
|
global $IP;
|
|
|
|
|
|
return self::getFileName( "$IP/languages/classes/Language", $code, '.php' );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
static function getLocalisationArray( $code, $disableCache = false ) {
|
|
|
|
|
|
self::loadLocalisation( $code, $disableCache );
|
|
|
|
|
|
return self::$mLocalisationCache[$code];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Load localisation data for a given code into the static cache
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return array Dependencies, map of filenames to mtimes
|
|
|
|
|
|
*/
|
|
|
|
|
|
static function loadLocalisation( $code, $disableCache = false ) {
|
|
|
|
|
|
static $recursionGuard = array();
|
2008-12-11 22:20:26 +00:00
|
|
|
|
global $wgMemc, $wgEnableSerializedMessages, $wgCheckSerialized;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
|
|
|
|
|
if ( !$code ) {
|
|
|
|
|
|
throw new MWException( "Invalid language code requested" );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( !$disableCache ) {
|
|
|
|
|
|
# Try the per-process cache
|
|
|
|
|
|
if ( isset( self::$mLocalisationCache[$code] ) ) {
|
|
|
|
|
|
return self::$mLocalisationCache[$code]['deps'];
|
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
wfProfileIn( __METHOD__ );
|
2006-01-17 23:43:15 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
# Try the serialized directory
|
2008-12-11 22:20:26 +00:00
|
|
|
|
if( $wgEnableSerializedMessages ) {
|
|
|
|
|
|
$cache = wfGetPrecompiledData( self::getFileName( "Messages", $code, '.ser' ) );
|
|
|
|
|
|
if ( $cache ) {
|
|
|
|
|
|
if ( $wgCheckSerialized && self::isLocalisationOutOfDate( $cache ) ) {
|
|
|
|
|
|
$cache = false;
|
|
|
|
|
|
wfDebug( "Language::loadLocalisation(): precompiled data file for $code is out of date\n" );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
self::$mLocalisationCache[$code] = $cache;
|
|
|
|
|
|
wfDebug( "Language::loadLocalisation(): got localisation for $code from precompiled data file\n" );
|
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
|
return self::$mLocalisationCache[$code]['deps'];
|
|
|
|
|
|
}
|
2007-11-30 17:03:12 +00:00
|
|
|
|
}
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Try the global cache
|
2008-06-01 03:27:48 +00:00
|
|
|
|
$memcKey = wfMemcKey('localisation', $code );
|
|
|
|
|
|
$fbMemcKey = wfMemcKey('fallback', $cache['fallback'] );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$cache = $wgMemc->get( $memcKey );
|
|
|
|
|
|
if ( $cache ) {
|
|
|
|
|
|
if ( self::isLocalisationOutOfDate( $cache ) ) {
|
|
|
|
|
|
$wgMemc->delete( $memcKey );
|
2008-04-27 14:37:37 +00:00
|
|
|
|
$wgMemc->delete( $fbMemcKey );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$cache = false;
|
2007-11-30 20:29:39 +00:00
|
|
|
|
wfDebug( "Language::loadLocalisation(): localisation cache for $code had expired\n" );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
self::$mLocalisationCache[$code] = $cache;
|
2007-01-06 18:20:58 +00:00
|
|
|
|
wfDebug( "Language::loadLocalisation(): got localisation for $code from cache\n" );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
|
return $cache['deps'];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
|
|
|
|
|
}
|
2004-08-06 21:19:24 +00:00
|
|
|
|
|
2006-11-18 18:45:34 +00:00
|
|
|
|
# Default fallback, may be overridden when the messages file is included
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ( $code != 'en' ) {
|
|
|
|
|
|
$fallback = 'en';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$fallback = false;
|
|
|
|
|
|
}
|
2006-11-18 18:45:34 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
# Load the primary localisation from the source file
|
2006-10-04 01:39:28 +00:00
|
|
|
|
$filename = self::getMessagesFileName( $code );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ( !file_exists( $filename ) ) {
|
2007-01-06 18:20:58 +00:00
|
|
|
|
wfDebug( "Language::loadLocalisation(): no localisation file for $code, using implicit fallback to en\n" );
|
2008-06-03 20:15:16 +00:00
|
|
|
|
$cache = compact( self::$mLocalisationKeys ); // Set correct fallback
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$deps = array();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$deps = array( $filename => filemtime( $filename ) );
|
|
|
|
|
|
require( $filename );
|
2008-05-27 09:19:24 +00:00
|
|
|
|
$cache = compact( self::$mLocalisationKeys );
|
2007-01-06 18:20:58 +00:00
|
|
|
|
wfDebug( "Language::loadLocalisation(): got localisation for $code from source\n" );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
2006-11-18 18:45:34 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
if ( !empty( $fallback ) ) {
|
|
|
|
|
|
# Load the fallback localisation, with a circular reference guard
|
|
|
|
|
|
if ( isset( $recursionGuard[$code] ) ) {
|
|
|
|
|
|
throw new MWException( "Error: Circular fallback reference in language code $code" );
|
|
|
|
|
|
}
|
|
|
|
|
|
$recursionGuard[$code] = true;
|
2006-08-14 23:10:58 +00:00
|
|
|
|
$newDeps = self::loadLocalisation( $fallback, $disableCache );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
unset( $recursionGuard[$code] );
|
|
|
|
|
|
|
|
|
|
|
|
$secondary = self::$mLocalisationCache[$fallback];
|
|
|
|
|
|
$deps = array_merge( $deps, $newDeps );
|
|
|
|
|
|
|
|
|
|
|
|
# Merge the fallback localisation with the current localisation
|
|
|
|
|
|
foreach ( self::$mLocalisationKeys as $key ) {
|
|
|
|
|
|
if ( isset( $cache[$key] ) ) {
|
|
|
|
|
|
if ( isset( $secondary[$key] ) ) {
|
|
|
|
|
|
if ( in_array( $key, self::$mMergeableMapKeys ) ) {
|
|
|
|
|
|
$cache[$key] = $cache[$key] + $secondary[$key];
|
|
|
|
|
|
} elseif ( in_array( $key, self::$mMergeableListKeys ) ) {
|
|
|
|
|
|
$cache[$key] = array_merge( $secondary[$key], $cache[$key] );
|
2006-10-30 06:25:31 +00:00
|
|
|
|
} elseif ( in_array( $key, self::$mMergeableAliasListKeys ) ) {
|
|
|
|
|
|
$cache[$key] = array_merge_recursive( $cache[$key], $secondary[$key] );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$cache[$key] = $secondary[$key];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Merge bookstore lists if requested
|
|
|
|
|
|
if ( !empty( $cache['bookstoreList']['inherit'] ) ) {
|
|
|
|
|
|
$cache['bookstoreList'] = array_merge( $cache['bookstoreList'], $secondary['bookstoreList'] );
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( isset( $cache['bookstoreList']['inherit'] ) ) {
|
|
|
|
|
|
unset( $cache['bookstoreList']['inherit'] );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Add dependencies to the cache entry
|
|
|
|
|
|
$cache['deps'] = $deps;
|
|
|
|
|
|
|
2006-09-05 17:06:48 +00:00
|
|
|
|
# Replace spaces with underscores in namespace names
|
|
|
|
|
|
$cache['namespaceNames'] = str_replace( ' ', '_', $cache['namespaceNames'] );
|
2007-12-22 19:46:12 +00:00
|
|
|
|
|
2008-06-25 13:50:46 +00:00
|
|
|
|
# And do the same for specialpage aliases. $page is an array.
|
|
|
|
|
|
foreach ( $cache['specialPageAliases'] as &$page ) {
|
|
|
|
|
|
$page = str_replace( ' ', '_', $page );
|
|
|
|
|
|
}
|
|
|
|
|
|
# Decouple the reference to prevent accidental damage
|
|
|
|
|
|
unset($page);
|
2006-09-05 17:06:48 +00:00
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
# Save to both caches
|
|
|
|
|
|
self::$mLocalisationCache[$code] = $cache;
|
|
|
|
|
|
if ( !$disableCache ) {
|
|
|
|
|
|
$wgMemc->set( $memcKey, $cache );
|
2008-04-27 14:49:40 +00:00
|
|
|
|
$wgMemc->set( $fbMemcKey, (string) $cache['fallback'] );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
|
return $deps;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Test if a given localisation cache is out of date with respect to the
|
|
|
|
|
|
* source Messages files. This is done automatically for the global cache
|
|
|
|
|
|
* in $wgMemc, but is only done on certain occasions for the serialized
|
|
|
|
|
|
* data file.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param $cache mixed Either a language code or a cache array
|
|
|
|
|
|
*/
|
|
|
|
|
|
static function isLocalisationOutOfDate( $cache ) {
|
|
|
|
|
|
if ( !is_array( $cache ) ) {
|
|
|
|
|
|
self::loadLocalisation( $cache );
|
|
|
|
|
|
$cache = self::$mLocalisationCache[$cache];
|
|
|
|
|
|
}
|
|
|
|
|
|
$expired = false;
|
|
|
|
|
|
foreach ( $cache['deps'] as $file => $mtime ) {
|
2006-10-04 02:12:52 +00:00
|
|
|
|
if ( !file_exists( $file ) || filemtime( $file ) > $mtime ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$expired = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return $expired;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Get the fallback for a given language
|
|
|
|
|
|
*/
|
|
|
|
|
|
static function getFallbackFor( $code ) {
|
2008-05-10 12:55:59 +00:00
|
|
|
|
// Shortcut
|
2008-04-27 14:55:15 +00:00
|
|
|
|
if ( $code === 'en' ) return false;
|
|
|
|
|
|
|
2008-05-10 12:55:59 +00:00
|
|
|
|
// Local cache
|
|
|
|
|
|
static $cache = array();
|
|
|
|
|
|
// Quick return
|
|
|
|
|
|
if ( isset($cache[$code]) ) return $cache[$code];
|
|
|
|
|
|
|
|
|
|
|
|
// Try memcache
|
2008-04-27 14:37:37 +00:00
|
|
|
|
global $wgMemc;
|
2008-06-01 03:27:48 +00:00
|
|
|
|
$memcKey = wfMemcKey( 'fallback', $code );
|
2008-04-27 14:37:37 +00:00
|
|
|
|
$fbcode = $wgMemc->get( $memcKey );
|
|
|
|
|
|
|
2008-05-02 16:04:06 +00:00
|
|
|
|
if ( is_string($fbcode) ) {
|
2008-05-10 12:55:59 +00:00
|
|
|
|
// False is stored as a string to detect failures in memcache properly
|
2008-04-27 14:49:40 +00:00
|
|
|
|
if ( $fbcode === '' ) $fbcode = false;
|
2008-05-10 12:55:59 +00:00
|
|
|
|
|
|
|
|
|
|
// Update local cache and return
|
|
|
|
|
|
$cache[$code] = $fbcode;
|
2008-04-27 14:37:37 +00:00
|
|
|
|
return $fbcode;
|
|
|
|
|
|
}
|
2008-05-10 12:55:59 +00:00
|
|
|
|
|
|
|
|
|
|
// Nothing in caches, load and and update both caches
|
2006-07-26 07:15:39 +00:00
|
|
|
|
self::loadLocalisation( $code );
|
2008-04-27 14:37:37 +00:00
|
|
|
|
$fbcode = self::$mLocalisationCache[$code]['fallback'];
|
2008-05-10 12:55:59 +00:00
|
|
|
|
|
|
|
|
|
|
$cache[$code] = $fbcode;
|
2008-04-27 14:49:40 +00:00
|
|
|
|
$wgMemc->set( $memcKey, (string) $fbcode );
|
2008-05-10 12:55:59 +00:00
|
|
|
|
|
2008-04-27 14:37:37 +00:00
|
|
|
|
return $fbcode;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Get all messages for a given language
|
|
|
|
|
|
*/
|
|
|
|
|
|
static function getMessagesFor( $code ) {
|
|
|
|
|
|
self::loadLocalisation( $code );
|
|
|
|
|
|
return self::$mLocalisationCache[$code]['messages'];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-08-07 12:21:06 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Get a message for a given language
|
|
|
|
|
|
*/
|
|
|
|
|
|
static function getMessageFor( $key, $code ) {
|
|
|
|
|
|
self::loadLocalisation( $code );
|
2006-11-29 05:45:03 +00:00
|
|
|
|
return isset( self::$mLocalisationCache[$code]['messages'][$key] ) ? self::$mLocalisationCache[$code]['messages'][$key] : null;
|
2006-08-07 12:21:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Load localisation data for this object
|
|
|
|
|
|
*/
|
|
|
|
|
|
function load() {
|
|
|
|
|
|
if ( !$this->mLoaded ) {
|
|
|
|
|
|
self::loadLocalisation( $this->getCode() );
|
|
|
|
|
|
$cache =& self::$mLocalisationCache[$this->getCode()];
|
|
|
|
|
|
foreach ( self::$mLocalisationKeys as $key ) {
|
|
|
|
|
|
$this->$key = $cache[$key];
|
|
|
|
|
|
}
|
|
|
|
|
|
$this->mLoaded = true;
|
|
|
|
|
|
|
|
|
|
|
|
$this->fixUpSettings();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Do any necessary post-cache-load settings adjustment
|
|
|
|
|
|
*/
|
|
|
|
|
|
function fixUpSettings() {
|
2007-01-12 07:26:32 +00:00
|
|
|
|
global $wgExtraNamespaces, $wgMetaNamespace, $wgMetaNamespaceTalk,
|
2006-07-26 07:15:39 +00:00
|
|
|
|
$wgNamespaceAliases, $wgAmericanDates;
|
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
|
|
|
|
|
if ( $wgExtraNamespaces ) {
|
|
|
|
|
|
$this->namespaceNames = $wgExtraNamespaces + $this->namespaceNames;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$this->namespaceNames[NS_PROJECT] = $wgMetaNamespace;
|
|
|
|
|
|
if ( $wgMetaNamespaceTalk ) {
|
|
|
|
|
|
$this->namespaceNames[NS_PROJECT_TALK] = $wgMetaNamespaceTalk;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$talk = $this->namespaceNames[NS_PROJECT_TALK];
|
|
|
|
|
|
$talk = str_replace( '$1', $wgMetaNamespace, $talk );
|
|
|
|
|
|
|
|
|
|
|
|
# Allow grammar transformations
|
|
|
|
|
|
# Allowing full message-style parsing would make simple requests
|
|
|
|
|
|
# such as action=raw much more expensive than they need to be.
|
|
|
|
|
|
# This will hopefully cover most cases.
|
2006-08-03 18:04:38 +00:00
|
|
|
|
$talk = preg_replace_callback( '/{{grammar:(.*?)\|(.*?)}}/i',
|
2006-08-02 03:19:55 +00:00
|
|
|
|
array( &$this, 'replaceGrammarInNamespace' ), $talk );
|
|
|
|
|
|
$talk = str_replace( ' ', '_', $talk );
|
2006-07-26 20:32:37 +00:00
|
|
|
|
$this->namespaceNames[NS_PROJECT_TALK] = $talk;
|
2006-07-26 07:15:39 +00:00
|
|
|
|
}
|
2006-07-26 20:37:11 +00:00
|
|
|
|
|
|
|
|
|
|
# The above mixing may leave namespaces out of canonical order.
|
|
|
|
|
|
# Re-order by namespace ID number...
|
|
|
|
|
|
ksort( $this->namespaceNames );
|
2006-07-26 07:15:39 +00:00
|
|
|
|
|
|
|
|
|
|
# Put namespace names and aliases into a hashtable.
|
|
|
|
|
|
# If this is too slow, then we should arrange it so that it is done
|
|
|
|
|
|
# before caching. The catch is that at pre-cache time, the above
|
|
|
|
|
|
# class-specific fixup hasn't been done.
|
|
|
|
|
|
$this->mNamespaceIds = array();
|
|
|
|
|
|
foreach ( $this->namespaceNames as $index => $name ) {
|
|
|
|
|
|
$this->mNamespaceIds[$this->lc($name)] = $index;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( $this->namespaceAliases ) {
|
|
|
|
|
|
foreach ( $this->namespaceAliases as $name => $index ) {
|
|
|
|
|
|
$this->mNamespaceIds[$this->lc($name)] = $index;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( $wgNamespaceAliases ) {
|
|
|
|
|
|
foreach ( $wgNamespaceAliases as $name => $index ) {
|
|
|
|
|
|
$this->mNamespaceIds[$this->lc($name)] = $index;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( $this->defaultDateFormat == 'dmy or mdy' ) {
|
|
|
|
|
|
$this->defaultDateFormat = $wgAmericanDates ? 'mdy' : 'dmy';
|
|
|
|
|
|
}
|
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-08-02 03:19:55 +00:00
|
|
|
|
function replaceGrammarInNamespace( $m ) {
|
|
|
|
|
|
return $this->convertGrammar( trim( $m[2] ), trim( $m[1] ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
|
static function getCaseMaps() {
|
|
|
|
|
|
static $wikiUpperChars, $wikiLowerChars;
|
|
|
|
|
|
if ( isset( $wikiUpperChars ) ) {
|
|
|
|
|
|
return array( $wikiUpperChars, $wikiLowerChars );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
|
|
|
|
|
$arr = wfGetPrecompiledData( 'Utf8Case.ser' );
|
|
|
|
|
|
if ( $arr === false ) {
|
|
|
|
|
|
throw new MWException(
|
|
|
|
|
|
"Utf8Case.ser is missing, please run \"make\" in the serialized directory\n" );
|
|
|
|
|
|
}
|
|
|
|
|
|
extract( $arr );
|
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
|
return array( $wikiUpperChars, $wikiLowerChars );
|
|
|
|
|
|
}
|
Basic integrated audio/video support, with Ogg implementation.
* JavaScript video player based loosely on Greg Maxwell's player
* Image page text snippet customisation
* Abstraction of transform parameters in the parser. Introduced Linker::makeImageLink2().
* Made canRender(), mustRender() depend on file, not just on handler. Moved width=0, height=0 checking to ImageHandler::canRender(), since audio streams have width=height=0 but should be rendered.
Also:
* Automatic upgrade for oldimage rows on image page view, allows media handler selection based on oi_*_mime
* oi_*_mime unconditionally referenced, REQUIRES SCHEMA UPGRADE
* Don't destroy file info for missing files on upgrade
* Simple, centralised extension message file handling
* Made MessageCache::loadAllMessages non-static, optimised for repeated-call case due to abuse in User.php
* Support for lightweight parser output hooks, with callback whitelist for security
* Moved Linker::formatSize() to Language, to join the new formatTimePeriod() and formatBitrate()
* Introduced MagicWordArray, regex capture trick requires that magic word IDs DO NOT CONTAIN HYPHENS.
2007-08-15 10:50:09 +00:00
|
|
|
|
|
|
|
|
|
|
function formatTimePeriod( $seconds ) {
|
|
|
|
|
|
if ( $seconds < 10 ) {
|
|
|
|
|
|
return $this->formatNum( sprintf( "%.1f", $seconds ) ) . wfMsg( 'seconds-abbrev' );
|
|
|
|
|
|
} elseif ( $seconds < 60 ) {
|
|
|
|
|
|
return $this->formatNum( round( $seconds ) ) . wfMsg( 'seconds-abbrev' );
|
|
|
|
|
|
} elseif ( $seconds < 3600 ) {
|
|
|
|
|
|
return $this->formatNum( floor( $seconds / 60 ) ) . wfMsg( 'minutes-abbrev' ) .
|
|
|
|
|
|
$this->formatNum( round( fmod( $seconds, 60 ) ) ) . wfMsg( 'seconds-abbrev' );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$hours = floor( $seconds / 3600 );
|
|
|
|
|
|
$minutes = floor( ( $seconds - $hours * 3600 ) / 60 );
|
|
|
|
|
|
$secondsPart = round( $seconds - $hours * 3600 - $minutes * 60 );
|
|
|
|
|
|
return $this->formatNum( $hours ) . wfMsg( 'hours-abbrev' ) .
|
|
|
|
|
|
$this->formatNum( $minutes ) . wfMsg( 'minutes-abbrev' ) .
|
|
|
|
|
|
$this->formatNum( $secondsPart ) . wfMsg( 'seconds-abbrev' );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function formatBitrate( $bps ) {
|
|
|
|
|
|
$units = array( 'bps', 'kbps', 'Mbps', 'Gbps' );
|
|
|
|
|
|
if ( $bps <= 0 ) {
|
|
|
|
|
|
return $this->formatNum( $bps ) . $units[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
$unitIndex = floor( log10( $bps ) / 3 );
|
|
|
|
|
|
$mantissa = $bps / pow( 1000, $unitIndex );
|
|
|
|
|
|
if ( $mantissa < 10 ) {
|
|
|
|
|
|
$mantissa = round( $mantissa, 1 );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$mantissa = round( $mantissa );
|
|
|
|
|
|
}
|
|
|
|
|
|
return $this->formatNum( $mantissa ) . $units[$unitIndex];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Format a size in bytes for output, using an appropriate
|
|
|
|
|
|
* unit (B, KB, MB or GB) according to the magnitude in question
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param $size Size to format
|
|
|
|
|
|
* @return string Plain text (not HTML)
|
|
|
|
|
|
*/
|
|
|
|
|
|
function formatSize( $size ) {
|
|
|
|
|
|
// For small sizes no decimal places necessary
|
|
|
|
|
|
$round = 0;
|
|
|
|
|
|
if( $size > 1024 ) {
|
|
|
|
|
|
$size = $size / 1024;
|
|
|
|
|
|
if( $size > 1024 ) {
|
|
|
|
|
|
$size = $size / 1024;
|
|
|
|
|
|
// For MB and bigger two decimal places are smarter
|
|
|
|
|
|
$round = 2;
|
|
|
|
|
|
if( $size > 1024 ) {
|
|
|
|
|
|
$size = $size / 1024;
|
|
|
|
|
|
$msg = 'size-gigabytes';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$msg = 'size-megabytes';
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$msg = 'size-kilobytes';
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$msg = 'size-bytes';
|
|
|
|
|
|
}
|
|
|
|
|
|
$size = round( $size, $round );
|
|
|
|
|
|
$text = $this->getMessageFromDB( $msg );
|
|
|
|
|
|
return str_replace( '$1', $this->formatNum( $size ), $text );
|
|
|
|
|
|
}
|
2007-11-13 04:05:13 +00:00
|
|
|
|
}
|