* (bug 39273) Added AJAX support for "Show changes" (diff) in LivePreview.
* Added ResourceLoader module "jquery.badge".
* mw.util.$content now points to the overall content area in the skin rather than just
- page text content area. If you need the old behaviour please use $( '#mw-content-text').
+ page text content area. If you need the old behavior please use $( '#mw-content-text').
* jsMessage has been replaced with a floating bubble notification system complete
with auto-hide, multi-message support, and message replacement tags.
* jquery.messageBox which appears to be unused by both core and extensions has
* New maintenance script to refresh image metadata (maintenance/refreshImageMetadata.php).
* (bug 16428) Include permalink in printable version.
* (bug 30722) Add an identity collation that sorts things based on what the
- unicode code point is (aka pre-1.17 behaviour).
+ unicode code point is (aka pre-1.17 behavior).
* (bug 30940) Add a hook in User:getDefaultOptions.
To give extensions a better and more flexible way of providing default
values for preferences a hook has been introdiced in User:getDefaultOptions().
make wfTempDir() return a sane value for Windows on worst-case.
* (bug 24824) Support ImageMagick 6.5.6-2+ JPEG decoder size hint, to reduce
memory usage when such an ImageMagick is used for scaling.
-* Disable multithreaded behaviour in recent ImageMagick, to avoid a deadlock
+* Disable multithreaded behavior in recent ImageMagick, to avoid a deadlock
when a resource limit such as $wgMaxShellMemory is hit.
* (bug 24981) Allow extensions to access SpecialUpload variables again.
* (bug 20744) Wiki forgets about an uploaded file.
exist. In that case the URL will get (?|&)wpDestFile=<filename> appended to
it as appropriate.
* If $wgLocaltimezone is null, use the server's timezone as the default for
- signatures. This was always the behaviour documented in DefaultSettings.php
- but has not been the actual behaviour for some time: instead, UTC was used
+ signatures. This was always the behavior documented in DefaultSettings.php
+ but has not been the actual behavior for some time: instead, UTC was used
by default.
* Added $wgExtensionAssetsPath, to decouple assets serving from $wgScriptPath.
If not specified it will default to $wgScriptPath/extensions
* (bug 12644) Template list on edit page now sorted on preview
* (bug 14058) Support pipe trick for namespaces and interwikis with "-"
* Message name filter on Special:Allmessages now case-insensitive
-* (bug 13943) Fix image redirect behaviour on image pages
+* (bug 13943) Fix image redirect behavior on image pages
* (bug 14093) Do 'sysop' => 'protect' magic in Title::isValidMoveOperation
* (bug 14063) Power search form missing <label> for redirects check
* (bug 14111) Similar filename warning links now lead to correct page
to not check and assume they are always up to date)
* The rollback permission can now be rate-limited using the normal mechanism.
* New configuration variable $wgExtraLanguageNames
-* Behaviour of $wgAddGroups and $wgRemoveGroups changed. New behaviour:
+* Behavior of $wgAddGroups and $wgRemoveGroups changed. New behavior:
* * Granting the userrights privilege allows arbitrary changing of rights.
* * Without the userrights privilege, a user will be able to add and/or
remove the groups specified in $wgAddGroups and $wgRemoveGroups for
Message transformation mode has been removed, and replaced with "preprocess"
mode. This means that some MediaWiki namespace messages may need to be updated,
-especially ones which took advantage of the terribly counterintuitive behaviour
+especially ones which took advantage of the terribly counterintuitive behavior
of the former message mode.
The header identification routines for section edit and for numbering section
entry in the TOC, but will not have a section edit link. HTML-style headings
will also not have a section edit link. Valid wikitext headings present in the
template source text will get a template section edit link. This is a major
-break from previous behaviour, but I believe the effects are almost entirely
+break from previous behavior, but I believe the effects are almost entirely
beneficial.
The main motivation for making these changes was performance. The new two-pass
enabled by default.
* Added option to install to MyISAM
* (bug 9250) Remove hardcoded minimum image name length of three characters
-* Fixed DISPLAYTITLE behaviour to reject titles which don't normalise to the
+* Fixed DISPLAYTITLE behavior to reject titles which don't normalise to the
same title as the current page, and enabled per default
* Wrap site CSS and JavaScript in a <pre> tag, like user JS/CSS
* (bug 10196) Add classes and dir="ltr" to the <pre>s on CSS and JS pages (new
* Fix upload form display in right-to-left languages
* Fixed regression in blocking of username '0'
* (bug 9437) Don't overwrite edit form submission handler when setting up
- edit box scroll position preserve/restore behaviour
+ edit box scroll position preserve/restore behavior
* (bug 10805) Fix "undo" link when viewing the diff of the most recent
change to a page using "diff=0"
* (bug 10765) img_auth.php will now refuse logged-out requests where
to image/svg+xml after loading from the database.
* Workaround for djvutoxml bug #1704049 (poor performance). Use djvudump
instead.
-* Fixed odd behaviour in ImagePage on DjVu thumbnailing errors
+* Fixed odd behavior in ImagePage on DjVu thumbnailing errors
* (bug 5439) "Go" title search will now jump to shared/foreign Image: and
MediaWiki: pages that have not been locally edited.
* (bug 9630) Limits links in Whatlinkshere forgot about namespace filter
* New maintenance script to show the cached statistics : showStats.php.
* Count deleted edits when regenerating total edits in maintenance/initStats.php
* (bug 3706) Allow users to be exempted from IP blocks. The ipblock-exempt permission
- key has been added to enable this behaviour, by default assigned to sysops.
+ key has been added to enable this behavior, by default assigned to sysops.
* (bug 7948) importDump.php now warn that Recentchanges need to be rebuild.
* (bug 7667) allow XHTML namespaces customization
* (bug 8531) Correct local name of Lingála (patch by Raymond)
* (bug 6642) Don't offer to unlock the database when it isn't locked
* cleanupTitles.php changed from --dry-run option to --fix, so default
behavior is now a non-invasive check as with namespaceDupes.php
-* (bug 6660) Fix behaviour of EditPage::blockedPage() when the article does
+* (bug 6660) Fix behavior of EditPage::blockedPage() when the article does
not exist; now doesn't show the source box if the user hasn't provided it
(blocked mid-edit) and the page doesn't exist
* Improve default value of "blockedtext"
* (bug 6023) Fixed mismatch of 0/NULL for wl_notificationtimestamp; now notification
mails are working after 'Mark all pages visited' button on Special:Watchlist is clicked
* Made {{INT:}} a core parser function instead of a special case. The syntax
- and behaviour is largely unchanged.
+ and behavior is largely unchanged.
* (bug 7448) Fixing the native name for Ewe (ee)
* (bug 6864) Replace message 'editing' with new message 'editinguser' in Special:Userrights
to allow better localisation
* (bug 1283) Use underlining and borders to highlight additions/deletions
in diff-view
* Use user's local timezone in Special:Log display
-* Show filename for images in gallery by default (restore beta 3 behaviour)
+* Show filename for images in gallery by default (restore beta 3 behavior)
* (bug 1201) Double-escaping in brokenlinks, imagelinks, categorylinks, searchindex
* When using squid reverse proxy, cache the redirect to the Main_Page
* (bug 1302) Fix Norwegian language file
gl, hr, hsb, hu, is, it, kk, kl, ku, ky, la, lb, lt, lv, mk, mo, mt, nl, no,
oc, pl, pt, rm, ro, ru, rup, sco, sk, sl, smn, sq, sr, sv, tk, tl, tr, tt, uk,
uz, vi.
+* Added 'CategoryAfterPageAdded' and 'CategoryAfterPageRemoved' hooks.
+* (bug 33186) Add image rotation api "imagerotate"
=== Bug fixes in 1.21 ===
* (bug 40353) SpecialDoubleRedirect should support interwiki redirects.
"password mismatch" error.
* (bug 44599) On Special:Version, HEADs for submodule checkouts (e.g. for
extensions) performed using Git 1.7.8+ should now appear.
+* (bug 42184) $wgUploadSizeWarning missing second variable
+* (bug 40326) Check if files exist with a different extension during uploading
=== API changes in 1.21 ===
* prop=revisions can now report the contentmodel and contentformat.
an error during parameter validation if the parameter is given but not
recognized as an uploaded file.
* (bug 44244) prop=info may now return the number of people watching each page.
+* (bug 33304) list=allpages will no longer return duplicate entries when
+ querying protection.
+* (bug 33304) list=allpages will now find really old indefinite protections.
=== API internal changes in 1.21 ===
* For debugging only, a new global $wgDebugAPI removes many API restrictions when true.
Vector extension (and possibly disable its features using config settings if
you don't want them).
* Experimental IBM DB2 support was removed due to lack of interest and maintainership
+* BREAKING CHANGE: Filenames of maintenance scripts were standardized into
+ lowerCamelCase format, and made more explicit:
+ - clear_stats.php -> clearCacheStats.php
+ - clear_interwiki_cache.php -> clearInterwikiCache.php
+ - initStats.php -> initSiteStats.php
+ - proxy_check.php -> proxyCheck.php
+ - stats.php -> showCacheStats.php
+ - showStats.php -> showSiteStats.php.
+ Class names were renamed accordingly:
+ - clear_stats -> ClearCacheStats
+ - InitStats -> InitSiteStats
+ - CacheStats -> ShowCacheStats
+ - ShowStats -> ShowSiteStats.
+* BREAKING CHANGE: (bug 38244) Removed the mediawiki.api.titleblacklist module
+ and moved it to the TitleBlacklist extension.
== Compatibility ==
can change between release branches, e.g. $wgDisableUploads in 1.4 is replaced
with $wgEnableUploads in later versions. When upgrading, consult the release
notes to check for configuration changes which would alter the expected
-behaviour of MediaWiki.
+behavior of MediaWiki.
=== Check installed extensions ===
the defaults.
&$namespaces: Array of namespace numbers with corresponding canonical names
+'CategoryAfterPageAdded': After a page is added to a category.
+$category: Category that page was added to
+$wikiPage: WikiPage that was added
+
+'CategoryAfterPageRemoved': After a page is removed from a category.
+$category: Category that page was removed from
+$wikiPage: WikiPage that was removed
+
'CategoryPageView': Before viewing a categorypage in CategoryPage::view.
$catpage: CategoryPage instance
Title::isCssOrJsPage().
'TitleIsAlwaysKnown': Called when determining if a page exists. Allows
-overriding default behaviour for determining if a page exists. If $isKnown is
+overriding default behavior for determining if a page exists. If $isKnown is
kept as null, regular checks happen. If it's a boolean, this value is returned
by the isKnown method.
$title: Title object that is being checked
level /maintenance directory.
Example:
- php clear_stats.php
+ php clearCacheStats.php
The following parameters are available to all maintenance scripts
--help : Print a help message
controlled by: $wgStatsMethod
key: $wgDBname:stats:$key
ex: wikibd:stats:request_with_session
- stores: counter for statistics (see maintenance/stats.php script)
+ stores: counter for statistics (see maintenance/showCacheStats.php script)
expiry: none (?)
- cleared by: maintenance/clear_stats.php script
+ cleared by: maintenance/clearCacheStats.php script
User:
key: $wgDBname:user:id:$sId
protected function alterForm( HTMLForm $form ) {}
/**
- * Get the HTMLForm to control behaviour
+ * Get the HTMLForm to control behavior
* @return HTMLForm|null
*/
protected function getForm() {
* some stuff underneath (history etc); to do some processing on submission of that
* form (delete, protect, etc) and to do something exciting on 'success', be that
* display something new or redirect to somewhere. Some actions have more exotic
- * behaviour, but that's what subclassing is for :D
+ * behavior, but that's what subclassing is for :D
*/
public function show() {
$this->setHeaders();
return $this->mContent;
}
-
/**
* Get text content object
* Does *NOT* follow redirects.
'MWNamespace' => 'includes/Namespace.php',
'OldChangesList' => 'includes/ChangesList.php',
'OutputPage' => 'includes/OutputPage.php',
- 'Page' => 'includes/WikiPage.php',
+ 'Page' => 'includes/WikiPage.php',
'PageQueryPage' => 'includes/PageQueryPage.php',
'Pager' => 'includes/Pager.php',
'PasswordError' => 'includes/User.php',
'WikiError' => 'includes/WikiError.php',
'WikiErrorMsg' => 'includes/WikiError.php',
'WikiExporter' => 'includes/Export.php',
- 'WikiFilePage' => 'includes/WikiFilePage.php',
+ 'WikiFilePage' => 'includes/WikiFilePage.php',
'WikiImporter' => 'includes/Import.php',
- 'WikiPage' => 'includes/WikiPage.php',
+ 'WikiPage' => 'includes/WikiPage.php',
'WikiRevision' => 'includes/Import.php',
'WikiMap' => 'includes/WikiMap.php',
'WikiReference' => 'includes/WikiMap.php',
'ApiFormatXmlRsd' => 'includes/api/ApiRsd.php',
'ApiFormatYaml' => 'includes/api/ApiFormatYaml.php',
'ApiHelp' => 'includes/api/ApiHelp.php',
+ 'ApiImageRotate' => 'includes/api/ApiImageRotate.php',
'ApiImport' => 'includes/api/ApiImport.php',
'ApiImportReporter' => 'includes/api/ApiImport.php',
'ApiLogin' => 'includes/api/ApiLogin.php',
'LSLockManager' => 'includes/filebackend/lockmanager/LSLockManager.php',
'MemcLockManager' => 'includes/filebackend/lockmanager/MemcLockManager.php',
'QuorumLockManager' => 'includes/filebackend/lockmanager/QuorumLockManager.php',
- 'MySqlLockManager'=> 'includes/filebackend/lockmanager/DBLockManager.php',
- 'PostgreSqlLockManager'=> 'includes/filebackend/lockmanager/DBLockManager.php',
+ 'MySqlLockManager' => 'includes/filebackend/lockmanager/DBLockManager.php',
+ 'PostgreSqlLockManager' => 'includes/filebackend/lockmanager/DBLockManager.php',
'NullLockManager' => 'includes/filebackend/lockmanager/LockManager.php',
'FileOp' => 'includes/filebackend/FileOp.php',
'FileOpBatch' => 'includes/filebackend/FileOpBatch.php',
# This has the nice property that a /32 block is ranked equally with a
# single-IP block, which is exactly what it is...
- $score = self::TYPE_RANGE - 1 + ( $size / 128 );
+ $score = self::TYPE_RANGE - 1 + ( $size / 128 );
} else {
$score = $block->getType();
# the collation in the database differs from the one
# set in $wgCategoryCollation, pagination might go totally haywire.
$extraConds = array( 'cl_type' => $type );
- if ( $this->from[$type] !== null ) {
+ if ( isset( $this->from[$type] ) && $this->from[$type] !== null ) {
$extraConds[] = 'cl_sortkey >= '
. $dbr->addQuotes( $this->collation->getSortKey( $this->from[$type] ) );
- } elseif ( $this->until[$type] !== null ) {
+ } elseif ( isset( $this->until[$type] ) && $this->until[$type] !== null ) {
$extraConds[] = 'cl_sortkey < '
. $dbr->addQuotes( $this->collation->getSortKey( $this->until[$type] ) );
$this->flip[$type] = true;
* @return String: HTML output, possibly empty if there are no other pages
*/
private function getSectionPagingLinks( $type ) {
- if ( $this->until[$type] !== null ) {
+ if ( isset( $this->until[$type] ) && $this->until[$type] !== null ) {
return $this->pagingLinks( $this->nextPage[$type], $this->until[$type], $type );
- } elseif ( $this->nextPage[$type] !== null || $this->from[$type] !== null ) {
+ } elseif ( $this->nextPage[$type] !== null || ( isset( $this->from[$type] ) && $this->from[$type] !== null ) ) {
return $this->pagingLinks( $this->from[$type], $this->nextPage[$type], $type );
} else {
return '';
}
$fromOrUntil = false;
- if ( $this->from[$pagingType] !== null || $this->until[$pagingType] !== null ) {
+ if ( ( isset( $this->from[$pagingType] ) && $this->from[$pagingType] !== null ) ||
+ ( isset( $this->until[$pagingType] ) && $this->until[$pagingType] !== null )
+ ) {
$fromOrUntil = true;
}
}
}
-
/**
* Writer class which uses the DBA extension
*/
}
}
-
/**
* Generate a list of changes using the good old system (no javascript)
*/
}
}
-
/**
* Generate a list of changes using an Enhanced system (uses javascript).
*/
}
}
-
class IcuCollation extends Collation {
var $primaryCollator, $mainCollator, $locale;
var $firstLetterData;
);
/**
- * Additional characters (or character groups) to be considered first-letters
+ * Additional characters (or character groups) to be considered separate
+ * letters for given languages, compared to the data stored in the
+ * first-letters-root.ser file (which among others includes full basic latin,
+ * cyrillic and greek alphabets).
+ *
+ * "Separate letter" is a letter that would have a separate heading/section
+ * for it in a dictionary or a phone book in this language. This data isn't
+ * used for sorting (the ICU library handles that), only for deciding which
+ * characters (or character groups) to use as headings.
*
- * Generated based on the primary level of Unicode collation tailorings
- * available at http://developer.mimer.com/charts/tailorings.htm .
+ * Initially generated based on the primary level of Unicode collation
+ * tailorings available at http://developer.mimer.com/charts/tailorings.htm ,
+ * later modified.
*
* Empty arrays are intended; this signifies that the data for the language is
* available and that there are, in fact, no additional letters to consider.
*/
static $tailoringFirstLetters = array(
// Verified by native speakers
- 'pl' => array( "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ),
+ 'be' => array( "Ё" ),
+ 'be-tarask' => array( "Ё" ),
'fi' => array( "Å", "Ä", "Ö" ),
+ 'pl' => array( "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ),
+ 'ru' => array(),
// Not verified, but likely correct
'af' => array(),
'ast' => array( "CH", "LL", "Ñ" ),
'az' => array( "Ç", "Ə", "Ğ", "İ", "Ö", "Ş", "Ü" ),
- 'be' => array( "Ё" ),
'bg' => array(),
'br' => array( "CH", "C'H" ),
'bs' => array( "Č", "Ć", "DŽ", "Đ", "LJ", "NJ", "Š", "Ž" ),
'pt' => array(),
'rm' => array(),
'ro' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
- 'ru' => array(),
'rup' => array( "Ă", "Â", "Î", "Ľ", "Ń", "Ş", "Ţ" ),
'sco' => array(),
'sk' => array( "Ä", "Č", "CH", "Ô", "Š", "Ž" ),
'sr' => array(),
'sv' => array( "Å", "Ä", "Ö" ),
'tk' => array( "Ç", "Ä", "Ž", "Ň", "Ö", "Ş", "Ü", "Ý" ),
- 'tl' => array( "Ñ", "NG" ), /* 'fil' in the data source */
+ 'tl' => array( "Ñ", "NG" ),
'tr' => array( "Ç", "Ğ", "İ", "Ö", "Ş", "Ü" ),
'tt' => array( "Ә", "Ө", "Ү", "Җ", "Ң", "Һ" ),
'uk' => array( "Ґ", "Ь" ),
*/
var $stateStack;
-
/**
* The path stack is a stack of associative arrays with the following elements:
* name The name of top level of the path
*/
$wgScriptExtension = '.php';
-
/**@}*/
/************************************************************************//**
*/
$wgCustomConvertCommand = false;
+/** used for lossless jpeg rotation
+ *
+ * @since 1.21
+ * **/
+$wgJpegTran = '/usr/bin/jpegtran';
+
+
/**
* Some tests and extensions use exiv2 to manipulate the EXIF metadata in some
* image formats.
),
);
-
/** Determines if a failed virus scan (AV_SCAN_FAILED) will cause the file to be rejected. */
$wgAntivirusRequired = true;
/**@}*/ # End of DB settings }
-
/************************************************************************//**
* @name Text storage
* @{
/**
* Store sessions in an object cache, configured by $wgSessionCacheType. This
- * can be useful to improve performance, or to avoid the locking behaviour of
+ * can be useful to improve performance, or to avoid the locking behavior of
* PHP's default session handler, which tends to prevent multiple requests for
* the same user from acting concurrently.
*/
* change it in their preferences.
*
* This also defines the language of pages in the wiki. The content is wrapped
- * in a html element with lang=XX attribute. This behaviour can be overriden
+ * in a html element with lang=XX attribute. This behavior can be overriden
* via hooks, see Title::getPageLanguage.
*/
$wgLanguageCode = 'en';
*/
$wgSend404Code = true;
-
/**
* The $wgShowRollbackEditCount variable is used to show how many edits will be
* rollback. The numeric value of the varible are the limit up to are counted.
/** @} */ # End of resource loader settings }
-
/*************************************************************************//**
* @name Page title and interwiki link settings
* @{
*/
$wgMaxGeneratedPPNodeCount = 1000000;
-
/**
* Maximum recursion depth for templates within templates.
* The current parser adds two levels to the PHP call stack for each template,
$wgGroupPermissions['*']['createpage'] = true;
$wgGroupPermissions['*']['createtalk'] = true;
$wgGroupPermissions['*']['writeapi'] = true;
-//$wgGroupPermissions['*']['patrolmarks'] = false; // let anons see what was patrolled
+#$wgGroupPermissions['*']['patrolmarks'] = false; // let anons see what was patrolled
// Implicit group for all logged-in accounts
$wgGroupPermissions['user']['move'] = true;
$wgGroupPermissions['bot']['suppressredirect'] = true;
$wgGroupPermissions['bot']['apihighlimits'] = true;
$wgGroupPermissions['bot']['writeapi'] = true;
-#$wgGroupPermissions['bot']['editprotected'] = true; // can edit all protected pages without cascade protection enabled
+#$wgGroupPermissions['bot']['editprotected'] = true; // can edit all protected pages without cascade protection enabled
// Most extra permission abilities go to this group
$wgGroupPermissions['sysop']['block'] = true;
$wgGroupPermissions['sysop']['movefile'] = true;
$wgGroupPermissions['sysop']['unblockself'] = true;
$wgGroupPermissions['sysop']['suppressredirect'] = true;
-#$wgGroupPermissions['sysop']['upload_by_url'] = true;
-#$wgGroupPermissions['sysop']['mergehistory'] = true;
+#$wgGroupPermissions['sysop']['upload_by_url'] = true;
+#$wgGroupPermissions['sysop']['mergehistory'] = true;
// Permission to change users' group assignments
$wgGroupPermissions['bureaucrat']['userrights'] = true;
// Permission to export pages including linked pages regardless of $wgExportMaxLinkDepth
#$wgGroupPermissions['bureaucrat']['override-export-depth'] = true;
-#$wgGroupPermissions['sysop']['deletelogentry'] = true;
-#$wgGroupPermissions['sysop']['deleterevision'] = true;
+#$wgGroupPermissions['sysop']['deletelogentry'] = true;
+#$wgGroupPermissions['sysop']['deleterevision'] = true;
// To hide usernames from users and Sysops
#$wgGroupPermissions['suppress']['hideuser'] = true;
// To hide revisions/log items from users and Sysops
/** Port we want to scan for a proxy */
$wgProxyPorts = array( 80, 81, 1080, 3128, 6588, 8000, 8080, 8888, 65506 );
/** Script used to scan */
-$wgProxyScriptPath = "$IP/maintenance/proxy_check.php";
+$wgProxyScriptPath = "$IP/maintenance/proxyCheck.php";
/** */
$wgProxyMemcExpiry = 86400;
/** This should always be customised in LocalSettings.php */
*/
$wgCookieDomain = '';
-
/**
* Set this variable if you want to restrict cookies to a certain path within
* the domain specified by $wgCookieDomain.
),
);
-
/**
* Overwrite the caching key prefix with custom value.
* @since 1.19
/**
* Path to the GNU diff3 utility. If the file doesn't exist, edit conflicts will
- * fall back to the old behaviour (no merging).
+ * fall back to the old behavior (no merging).
*/
$wgDiff3 = '/usr/bin/diff3';
define( 'DB_WRITE', -2 );
define( 'DB_LAST', -3 ); # deprecated since 2008, usage throws exception
-
/**@{
* Virtual namespaces; don't appear in the page database
*/
/**
* Status: Article successfully updated
*/
- const AS_SUCCESS_UPDATE = 200;
+ const AS_SUCCESS_UPDATE = 200;
/**
* Status: Article successfully created
*/
- const AS_SUCCESS_NEW_ARTICLE = 201;
+ const AS_SUCCESS_NEW_ARTICLE = 201;
/**
* Status: Article update aborted by a hook function
*/
- const AS_HOOK_ERROR = 210;
+ const AS_HOOK_ERROR = 210;
/**
* Status: A hook function returned an error
*/
- const AS_HOOK_ERROR_EXPECTED = 212;
+ const AS_HOOK_ERROR_EXPECTED = 212;
/**
* Status: User is blocked from editting this page
*/
- const AS_BLOCKED_PAGE_FOR_USER = 215;
+ const AS_BLOCKED_PAGE_FOR_USER = 215;
/**
* Status: Content too big (> $wgMaxArticleSize)
*/
- const AS_CONTENT_TOO_BIG = 216;
+ const AS_CONTENT_TOO_BIG = 216;
/**
* Status: User cannot edit? (not used)
*/
- const AS_USER_CANNOT_EDIT = 217;
+ const AS_USER_CANNOT_EDIT = 217;
/**
* Status: this anonymous user is not allowed to edit this page
*/
- const AS_READ_ONLY_PAGE_ANON = 218;
+ const AS_READ_ONLY_PAGE_ANON = 218;
/**
* Status: this logged in user is not allowed to edit this page
*/
- const AS_READ_ONLY_PAGE_LOGGED = 219;
+ const AS_READ_ONLY_PAGE_LOGGED = 219;
/**
* Status: wiki is in readonly mode (wfReadOnly() == true)
*/
- const AS_READ_ONLY_PAGE = 220;
+ const AS_READ_ONLY_PAGE = 220;
/**
* Status: rate limiter for action 'edit' was tripped
*/
- const AS_RATE_LIMITED = 221;
+ const AS_RATE_LIMITED = 221;
/**
* Status: article was deleted while editting and param wpRecreate == false or form
* was not posted
*/
- const AS_ARTICLE_WAS_DELETED = 222;
+ const AS_ARTICLE_WAS_DELETED = 222;
/**
* Status: user tried to create this page, but is not allowed to do that
* ( Title->usercan('create') == false )
*/
- const AS_NO_CREATE_PERMISSION = 223;
+ const AS_NO_CREATE_PERMISSION = 223;
/**
* Status: user tried to create a blank page
*/
- const AS_BLANK_ARTICLE = 224;
+ const AS_BLANK_ARTICLE = 224;
/**
* Status: (non-resolvable) edit conflict
*/
- const AS_CONFLICT_DETECTED = 225;
+ const AS_CONFLICT_DETECTED = 225;
/**
* Status: no edit summary given and the user has forceeditsummary set and the user is not
* editting in his own userspace or talkspace and wpIgnoreBlankSummary == false
*/
- const AS_SUMMARY_NEEDED = 226;
+ const AS_SUMMARY_NEEDED = 226;
/**
* Status: user tried to create a new section without content
*/
- const AS_TEXTBOX_EMPTY = 228;
+ const AS_TEXTBOX_EMPTY = 228;
/**
* Status: article is too big (> $wgMaxArticleSize), after merging in the new section
/**
* not used
*/
- const AS_OK = 230;
+ const AS_OK = 230;
/**
* Status: WikiPage::doEdit() was unsuccessfull
*/
- const AS_END = 231;
+ const AS_END = 231;
/**
* Status: summary contained spam according to one of the regexes in $wgSummarySpamRegex
*/
- const AS_SPAM_ERROR = 232;
+ const AS_SPAM_ERROR = 232;
/**
* Status: anonymous user is not allowed to upload (User::isAllowed('upload') == false)
*/
- const AS_IMAGE_REDIRECT_ANON = 233;
+ const AS_IMAGE_REDIRECT_ANON = 233;
/**
* Status: logged in user is not allowed to upload (User::isAllowed('upload') == false)
*/
- const AS_IMAGE_REDIRECT_LOGGED = 234;
+ const AS_IMAGE_REDIRECT_LOGGED = 234;
/**
* Status: can't parse content
*/
- const AS_PARSE_ERROR = 240;
+ const AS_PARSE_ERROR = 240;
/**
* HTML id and name for the beginning of the edit form.
*/
- const EDITFORM_ID = 'editform';
+ const EDITFORM_ID = 'editform';
/**
* Prefix of key for cookie used to pass post-edit state.
$this->isConflict = false;
// css / js subpages of user pages get a special treatment
- $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage();
- $this->isCssSubpage = $this->mTitle->isCssSubpage();
- $this->isJsSubpage = $this->mTitle->isJsSubpage();
+ $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage();
+ $this->isCssSubpage = $this->mTitle->isCssSubpage();
+ $this->isJsSubpage = $this->mTitle->isJsSubpage();
$this->isWrongCaseCssJsPage = $this->isWrongCaseCssJsPage();
# Show applicable editing introductions
// Nothing *to* preview for new sections
return false;
} elseif ( ( $wgRequest->getVal( 'preload' ) !== null || $this->mTitle->exists() ) && $wgUser->getOption( 'previewonfirst' ) ) {
- // Standard preference behaviour
+ // Standard preference behavior
return true;
} elseif ( !$this->mTitle->exists() &&
isset( $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] ) &&
$this->starttime = null;
}
- $this->recreate = $request->getCheck( 'wpRecreate' );
+ $this->recreate = $request->getCheck( 'wpRecreate' );
$this->minoredit = $request->getCheck( 'wpMinoredit' );
$this->watchthis = $request->getCheck( 'wpWatchthis' );
} else {
# Not a posted form? Start with nothing.
wfDebug( __METHOD__ . ": Not a posted form.\n" );
- $this->textbox1 = '';
- $this->summary = '';
+ $this->textbox1 = '';
+ $this->summary = '';
$this->sectiontitle = '';
- $this->edittime = '';
- $this->starttime = wfTimestampNow();
- $this->edit = false;
- $this->preview = false;
- $this->save = false;
- $this->diff = false;
- $this->minoredit = false;
- $this->watchthis = $request->getBool( 'watchthis', false ); // Watch may be overriden by request parameters
- $this->recreate = false;
+ $this->edittime = '';
+ $this->starttime = wfTimestampNow();
+ $this->edit = false;
+ $this->preview = false;
+ $this->save = false;
+ $this->diff = false;
+ $this->minoredit = false;
+ $this->watchthis = $request->getBool( 'watchthis', false ); // Watch may be overriden by request parameters
+ $this->recreate = false;
// When creating a new section, we can preload a section title by passing it as the
// preloadtitle parameter in the URL (Bug 13100)
$rev = $this->mArticle->getRevision();
$content = $rev ? $rev->getContent( Revision::RAW ) : null;
- if ( $content === false || $content === null ) {
+ if ( $content === false || $content === null ) {
if ( !$this->contentModel ) $this->contentModel = $this->getTitle()->getContentModel();
$handler = ContentHandler::getForModelID( $this->contentModel );
}
}
-
/**
* Use this method before edit() to preload some text into the edit box
*
// FIXME: once the interface for internalAttemptSave() is made nicer, this should use the message in $status
if ( $status->value == self::AS_SUCCESS_UPDATE || $status->value == self::AS_SUCCESS_NEW_ARTICLE ) {
$this->didSave = true;
- $this->setPostEditCookie();
+ if ( !$resultDetails['nullEdit'] ) {
+ $this->setPostEditCookie();
+ }
}
switch ( $status->value ) {
/**
* Attempt submission (no UI)
*
- * @param $result
- * @param $bot bool
+ * @param array $result array to add statuses to, currently with the possible keys:
+ * spam - string - Spam string from content if any spam is detected by matchSpamRegex
+ * sectionanchor - string - Section anchor for a section save
+ * nullEdit - boolean - Set if doEditContent is OK. True if null edit, false otherwise.
+ * redirect - boolean - Set if doEditContent is OK. True if resulting revision is a redirect
+ * @param bool $bot True if edit is being made under the bot right.
*
* @return Status object, possibly with a message, but always with one of the AS_* constants in $status->value,
*
return $doEditStatus;
}
+ $result['nullEdit'] = $doEditStatus->hasMessage( 'edit-no-change' );
$result['redirect'] = $content->isRedirect();
$this->updateWatchlist();
wfProfileOut( __METHOD__ );
$this->showHeaderCopyrightWarning();
}
-
/**
* Standard summary input and label (wgSummary), abstracted so EditPage
* subclasses may reorganize the form.
$callargs = array_merge( array( $this ), $args );
foreach ( $hooks as $hook ) {
- if ( is_string( $hook ) || ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) ) ) { // 'function' or array( 'class', hook' )
+ if ( is_string( $hook ) || ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) ) ) { // 'function' or array( 'class', hook' )
$result = call_user_func_array( $hook, $callargs );
} else {
$result = null;
foreach ( $resultset as $row ) {
if ( $last === null ||
$last->page_namespace != $row->page_namespace ||
- $last->page_title != $row->page_title ) {
+ $last->page_title != $row->page_title ) {
if ( $last !== null ) {
$output = '';
if ( $this->dumpUploads ) {
}
if ( isset( $row->rev_minor_edit ) && $row->rev_minor_edit ) {
- $out .= " <minor/>\n";
+ $out .= " <minor/>\n";
}
if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_COMMENT ) ) {
$out .= " " . Xml::element( 'comment', array( 'deleted' => 'deleted' ) ) . "\n";
}
}
-
/**
* Base class for output stream; prints to stdout or buffer or whereever.
* @ingroup Dump
}
}
-
/**
* Dump output filter to include only the last revision in each page sequence.
* @ingroup Dump
return $total;
}
-
/**
* Fallback implementation of mb_strpos, hardcoded to UTF-8.
* @param $haystack String
}
}
-
// Support for Wietse Venema's taint feature
if ( !function_exists( 'istainted' ) ) {
/**
*
* @param $s String:
* @return string
-*/
+ */
function wfUrlencode( $s ) {
static $needle;
if ( is_null( $s ) ) {
return urldecode( $matches[1] );
}
-
-
/**
* Make URL indexes, appropriate for the el_index field of externallinks.
*
$frame['function'];
}
-
/* Some generic result counters, pulled out of SearchEngine */
-
/**
* @todo document
*
*/
class HTMLRadioField extends HTMLFormField {
-
function validate( $value, $alldata ) {
$p = parent::validate( $value, $alldata );
}
}
-
/**
* Pointer object for an item within a CGZ blob stored in the text table.
*/
}
}
-
/**
* To speed up conversion from 1.4 to 1.5 schema, text rows can refer to the
* leftover cur table as the backend. This avoids expensively copying hundreds
unset( self::$handlers[$name] );
}
-
/**
* Attach an event handler to a given hook
*
return (int)$this->respStatus;
}
-
/**
* Returns true if the last status code was a redirect.
*
if ( isset( $url['host'] ) ) {
$domain = $url[ 'scheme' ] . '://' . $url[ 'host' ];
- break; //found correct URI (with host)
+ break; //found correct URI (with host)
} else {
$foundRelativeURI = true;
}
return long2ip( ( hexdec( $m[1] ) << 16 ) + hexdec( $m[2] ) );
}
- return null; // give up
+ return null; // give up
}
/**
* @file
*/
-
/**
* Some functions to help implement an external link filter for spam control.
*
if ( $file && isset( $fp['frameless'] ) ) {
$srcWidth = $file->getWidth( $page );
# For "frameless" option: do not present an image bigger than the source (for bitmap-style images)
- # This is the same behaviour as the "thumb" option does it already.
+ # This is the same behavior as the "thumb" option does it already.
if ( $srcWidth && !$file->mustRender() && $hp['width'] > $srcWidth ) {
$hp['width'] = $srcWidth;
}
$noscale = true;
} else {
# Do not present an image bigger than the source, for bitmap-style images
- # This is a hack to maintain compatibility with arbitrary pre-1.10 behaviour
+ # This is a hack to maintain compatibility with arbitrary pre-1.10 behavior
$srcWidth = $file->getWidth( $page );
if ( $srcWidth && !$file->mustRender() && $hp['width'] > $srcWidth ) {
$hp['width'] = $srcWidth;
return self::userToolLinks( $userId, $userText, true, 0, $edits );
}
-
/**
* @param $userId Integer: user id in database.
* @param $userText String: user name in database.
}
}
-
/**
* Returns true if the text matches the word, and alters the
* input string, removing all instances of the word
* Call the parent constructor, then store the key as
* the message.
*
- * @param $key Message to use
- * @param $params Parameters for the message
+ * @param $key string Message to use
+ * @param $params array Parameters for the message
* @see Message::__construct
*/
public function __construct( $key, $params = array() ) {
class MimeMagic {
/**
- * Mapping of media types to arrays of mime types.
- * This is used by findMediaType and getMediaType, respectively
- */
+ * Mapping of media types to arrays of mime types.
+ * This is used by findMediaType and getMediaType, respectively
+ */
var $mMediaTypes = null;
/** Map of mime type aliases
- */
+ */
var $mMimeTypeAliases = null;
/** map of mime types to file extensions (as a space seprarated list)
- */
+ */
var $mMimeToExt = null;
/** map of file extensions types to mime types (as a space seprarated list)
- */
+ */
var $mExtToMime = null;
/** IEContentAnalyzer instance
*/
function __construct() {
/**
- * --- load mime.types ---
- */
+ * --- load mime.types ---
+ */
global $wgMimeTypeFile, $IP, $wgLoadFileinfoExtension;
return $m;
}
-
/**
* Tests if the extension matches the given mime type. Returns true if a
* match was found, null if the mime type is unknown, and false if the
$ext = $this->getExtensionsForType( $mime );
if ( !$ext ) {
- return null; // Unknown mime type
+ return null; // Unknown mime type
}
$ext = explode( ' ', $ext );
# TODO: remove the block below, as soon as improveTypeFromExtension is used everywhere
if ( $ext !== true && $ext !== false ) {
/** This is the mode used by getPropsFromPath
- * These mime's are stored in the database, where we don't really want
- * x-opc+zip, because we use it only for internal purposes
- */
+ * These mime's are stored in the database, where we don't really want
+ * x-opc+zip, because we use it only for internal purposes
+ */
if ( $this->isMatchingExtension( $ext, $mime) ) {
/* A known file extension for an OPC file,
- * find the proper mime type for that file extension */
+ * find the proper mime type for that file extension
+ */
$mime = $this->guessTypesForExtension( $ext );
} else {
$mime = "application/zip";
$this->addHTML( $text );
}
-
/**
* Add the output of a QuickTemplate to the output buffer
*
$this->mJsConfigVars[$keys] = $value;
}
-
/**
* Get an array containing the variables to be set in mw.config in JavaScript.
*
) );
}
-
# Language variants
if ( !$wgDisableLangConversion && $wgCanonicalLanguageLinks ) {
$lang = $this->getTitle()->getPageLanguage();
protected function getDefaultDirections() { return false; }
}
-
/**
* IndexPager with an alphabetic list and a formatted navigation bar
* @ingroup Pager
abstract class PoolCounter {
/* Return codes */
- const LOCKED = 1; /* Lock acquired */
+ const LOCKED = 1; /* Lock acquired */
const RELEASED = 2; /* Lock released */
- const DONE = 3; /* Another worker did the work for you */
+ const DONE = 3; /* Another worker did the work for you */
- const ERROR = -1; /* Indeterminate error */
+ const ERROR = -1; /* Indeterminate error */
const NOT_LOCKED = -2; /* Called release() with no lock held */
const QUEUE_FULL = -3; /* There are already maxqueue workers on this lock */
- const TIMEOUT = -4; /* Timeout exceeded */
- const LOCK_HELD = -5; /* Cannot acquire another lock while you have one lock held */
+ const TIMEOUT = -4; /* Timeout exceeded */
+ const LOCK_HELD = -5; /* Cannot acquire another lock while you have one lock held */
/**
* I want to do this task and I need to do it myself.
protected function __construct( $conf, $type, $key ) {
$this->key = $key;
- $this->workers = $conf['workers'];
+ $this->workers = $conf['workers'];
$this->maxqueue = $conf['maxqueue'];
- $this->timeout = $conf['timeout'];
+ $this->timeout = $conf['timeout'];
}
}
// Skip the default * group, seems useless here
continue;
}
- $groupName = User::getGroupName( $ueg );
+ $groupName = User::getGroupName( $ueg );
$userGroups[] = User::makeGroupLinkHTML( $ueg, $groupName );
$memberName = User::getGroupMember( $ueg, $userName );
);
}
-
$defaultPreferences['emailaddress'] = array(
'type' => 'info',
'raw' => true,
'label-message' => 'tog-forceeditsummary',
);
-
$defaultPreferences['uselivepreview'] = array(
'type' => 'toggle',
'section' => 'editing/advancedediting',
'min' => 0,
);
-
if ( $wgVectorUseSimpleSearch ) {
$defaultPreferences['vector-simplesearch'] = array(
'type' => 'toggle',
# Add manual and custom reason field/selects as well as submit
if( !$this->disabled ) {
- $out .= Xml::openElement( 'table', array( 'id' => 'mw-protect-table3' ) ) .
+ $out .= Xml::openElement( 'table', array( 'id' => 'mw-protect-table3' ) ) .
Xml::openElement( 'tbody' );
$out .= "
<tr>
if ( !$wgDisableCounters )
$wgQueryPages[] = array( 'PopularPagesPage', 'Popularpages' );
-
/**
* This is a class for doing query pages; since they're almost all the same,
* we factor out some of the functionality into a superclass, and let
'rc_params' => ''
);
- $rc->mExtra = array(
+ $rc->mExtra = array(
'prefixedDBkey' => $title->getPrefixedDBkey(),
'lastTimestamp' => $lastTimestamp,
'oldSize' => $oldSize,
'rc_params' => ''
);
- $rc->mExtra = array(
+ $rc->mExtra = array(
'prefixedDBkey' => $title->getPrefixedDBkey(),
'lastTimestamp' => 0,
'oldSize' => 0,
'rc_params' => $params
);
- $rc->mExtra = array(
+ $rc->mExtra = array(
'prefixedDBkey' => $title->getPrefixedDBkey(),
'lastTimestamp' => 0,
'actionComment' => $actionComment, // the comment appended to the action, passed from LogPage
// Build a new revision to be saved...
global $wgUser; // ugh
-
# if we have a content object, use it to set the model and type
if ( !empty( $row['content'] ) ) {
//@todo: when is that set? test with external store setup! check out insertOn() [dk]
/**
* Get previous revision for this title
*
- * @return Revision or null
+ * @return Revision|null
*/
public function getPrevious() {
if( $this->getTitle() ) {
if ( $wgContentHandlerUseDB ) {
//NOTE: Store null for the default model and format, to save space.
- //XXX: Makes the DB sensitive to changed defaults. Make this behaviour optional? Only in miser mode?
+ //XXX: Makes the DB sensitive to changed defaults. Make this behavior optional? Only in miser mode?
$model = $this->getContentModel();
$format = $this->getContentFormat();
// Please note strings below are enclosed in brackets [], this make the
// hyphen "-" a range indicator. Hence it is double backslashed below.
// See bug 26948
- $rfc5322_atext = "a-z0-9!#$%&'*+\\-\/=?^_`{|}~";
+ $rfc5322_atext = "a-z0-9!#$%&'*+\\-\/=?^_`{|}~";
$rfc1034_ldh_str = "a-z0-9\\-";
$HTML5_email_regexp = "/
if ( $wgStylePath === false ) $wgStylePath = "$wgScriptPath/skins";
if ( $wgLocalStylePath === false ) $wgLocalStylePath = "$wgScriptPath/skins";
-if ( $wgStyleDirectory === false ) $wgStyleDirectory = "$IP/skins";
+if ( $wgStyleDirectory === false ) $wgStyleDirectory = "$IP/skins";
if ( $wgExtensionAssetsPath === false ) $wgExtensionAssetsPath = "$wgScriptPath/extensions";
if ( $wgLogo === false ) $wgLogo = "$wgStylePath/common/images/wiki.png";
( $this->getTitle()->getArticleID() == 0 || $action == 'history' ) ) {
$n = $this->getTitle()->isDeleted();
-
if ( $n ) {
if ( $this->getUser()->isAllowed( 'undelete' ) ) {
$msg = 'thisisdeleted';
return '';
}
- # __NEWSECTIONLINK___ changes behaviour here
+ # __NEWSECTIONLINK___ changes behavior here
# If it is present, the link points to this page, otherwise
# it points to the talk page
if ( !$title->isTalkPage() && !$wgOut->showNewSectionLink() ) {
$userLang = $this->getLanguage();
$userLangCode = $userLang->getHtmlCode();
- $userLangDir = $userLang->getDir();
+ $userLangDir = $userLang->getDir();
$tpl->set( 'lang', $userLangCode );
$tpl->set( 'dir', $userLangDir );
* be displayed by the default execute() method, without the global function ever
* being called.
*
- * If you override execute(), you can recover the default behaviour with userCanExecute()
+ * If you override execute(), you can recover the default behavior with userCanExecute()
* and displayRestrictionError()
*
* @param $name String: name of the special page, as seen in links and URLs
* also the name that will be listed in Special:Specialpages
*
* Derived classes can override this, but usually it is easier to keep the
- * default behaviour. Messages can be added at run-time, see
+ * default behavior. Messages can be added at run-time, see
* MessageCache.php.
*
* @return String
}
/**
- * Get the HTMLForm to control behaviour
+ * Get the HTMLForm to control behavior
* @return HTMLForm|null
*/
protected function getForm() {
* memory. The delimiters are literal strings, not regular expressions.
*
* If the start delimiter ends with an initial substring of the end delimiter,
- * e.g. in the case of C-style comments, the behaviour differs from the model
+ * e.g. in the case of C-style comments, the behavior differs from the model
* regex. In this implementation, the end must share no characters with the
* start, so e.g. /*\/ is not considered to be both the start and end of a
* comment. /*\/xy/*\/ is considered to be a single comment with contents /xy/.
var $mHasSubpage; // /< Whether a page has any subpages
// @}
-
/**
* Constructor
*/
strpos( $dbkey, '.' ) !== false &&
(
$dbkey === '.' || $dbkey === '..' ||
- strpos( $dbkey, './' ) === 0 ||
+ strpos( $dbkey, './' ) === 0 ||
strpos( $dbkey, '../' ) === 0 ||
strpos( $dbkey, '/./' ) !== false ||
- strpos( $dbkey, '/../' ) !== false ||
+ strpos( $dbkey, '/../' ) !== false ||
substr( $dbkey, -2 ) == '/.' ||
substr( $dbkey, -3 ) == '/..'
)
return $retVal;
}
-
/**
* Get a list of URLs to purge from the Squid cache when this
* page changes
$isKnown = null;
/**
- * Allows overriding default behaviour for determining if a page exists.
+ * Allows overriding default behavior for determining if a page exists.
* If $isKnown is kept as null, regular checks happen. If it's
* a boolean, this value is returned by the isKnown method.
*
return false;
}
-
// Ensure that the name can't be misresolved as a different title,
// such as with extra namespace keys at the start.
$parsed = Title::newFromText( $name );
* @note This no longer clears uncached lazy-initialised properties;
* the constructor does that instead.
*
- * @param $name string
+ * @param $name string|bool
*/
public function loadDefaults( $name = false ) {
wfProfileIn( __METHOD__ );
}
}
-
/**
* Get blocking information
* @param $bFromSlave Bool Whether to check the slave database first. To
/**
* Get the user's current token.
- * @param $forceCreation Force the generation of a new token if the user doesn't have one (default=true for backwards compatibility)
+ * @param $forceCreation bool Force the generation of a new token if the user doesn't have one (default=true for backwards compatibility)
* @return String Token
*/
public function getToken( $forceCreation = true ) {
*
* @param $request WebRequest object to use; $wgRequest will be used if null
* is passed.
- * @param $secure Whether to force secure/insecure cookies or use default
+ * @param $secure bool Whether to force secure/insecure cookies or use default
*/
public function setCookies( $request = null, $secure = null ) {
if ( $request === null ) {
}
$this->load();
- if ( 0 == $this->mId ) return;
+ if ( 0 == $this->mId ) {
+ return;
+ }
if ( !$this->mToken ) {
// When token is empty or NULL generate a new one and then save it to the database
// This allows a wiki to re-secure itself after a leak of it's user table or $wgSecretKey
// since it disables the parser cache, its value will always
// be 0 when this function is called by parsercache.
- $confstr = $this->getOption( 'math' );
+ $confstr = $this->getOption( 'math' );
$confstr .= '!' . $this->getStubThreshold();
$confstr .= '!' . ( $this->getOption( 'numberheadings' ) ? '1' : '' );
$confstr .= '!' . $wgLang->getCode();
/**
* Generate a looking random token for various uses.
*
- * @param $salt String Optional salt value
* @return String The new random token
* @deprecated since 1.20; Use MWCryptRand for secure purposes or wfRandomString for pesudo-randomness
*/
- public static function generateToken( $salt = '' ) {
+ public static function generateToken() {
return MWCryptRand::generateHex( 32 );
}
}
/**
- * Return a URL the user can use to confirm their email address.
+ * Return a URL the user can use to confirm their email address.
* @param $token String Accepts the email confirmation token
* @return String New token URL
*/
/**
* Load the user options either from cache, the database or an array
*
- * @param $data Rows for the current user out of the user_properties table
+ * @param $data array Rows for the current user out of the user_properties table
*/
protected function loadOptions( $data = null ) {
global $wgContLang;
* @author Luke Welling lwelling@wikimedia.org
*/
-
/**
* Stores a single person's name and email address.
* These are passed in via the constructor, and will be returned in SMTP
}
}
-
/**
* Collection of static functions for sending mail
*/
$mime = new Mail_mime( array( 'eol' => $endl ) );
$mime->setTXTBody( $body['text'] );
$mime->setHTMLBody( $body['html'] );
- $body = $mime->get(); // must call get() before headers()
+ $body = $mime->get(); // must call get() before headers()
$headers = $mime->headers( $headers );
}
}
$success = true;
}
- # the following code compensates the new behaviour, introduced by the
+ # the following code compensates the new behavior, introduced by the
# enotif patch, that every single watched page needs now to be listed
# in watchlist namespace:page and namespace_talk:page had separate
# entries: clear them
// Check for redirects ...
$action = $request->getVal( 'action', 'view' );
$file = ( $title->getNamespace() == NS_FILE ) ? $article->getFile() : null;
- if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content
- && !$request->getVal( 'oldid' ) && // ... and are not old revisions
- !$request->getVal( 'diff' ) && // ... and not when showing diff
- $request->getVal( 'redirect' ) != 'no' && // ... unless explicitly told not to
+ if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content
+ && !$request->getVal( 'oldid' ) && // ... and are not old revisions
+ !$request->getVal( 'diff' ) && // ... and not when showing diff
+ $request->getVal( 'redirect' ) != 'no' && // ... unless explicitly told not to
// ... and the article is not a non-redirect image page with associated file
!( is_object( $file ) && $file->exists() && !$file->getRedirected() ) )
{
public $mPreparedEdit = false; // !< Array
/**@}}*/
+ /**
+ * @var int
+ */
+ protected $mId = null;
+
/**
* @var int; one of the READ_* constants
*/
* @return void
*/
protected function clearCacheFields() {
+ $this->mId = null;
$this->mCounter = null;
$this->mRedirectTarget = null; // Title object if set
$this->mLastRevision = null; // Latest revision
// Old-fashioned restrictions
$this->mTitle->loadRestrictions( $data->page_restrictions );
- $this->mCounter = intval( $data->page_counter );
- $this->mTouched = wfTimestamp( TS_MW, $data->page_touched );
- $this->mIsRedirect = intval( $data->page_is_redirect );
- $this->mLatest = intval( $data->page_latest );
+ $this->mId = intval( $data->page_id );
+ $this->mCounter = intval( $data->page_counter );
+ $this->mTouched = wfTimestamp( TS_MW, $data->page_touched );
+ $this->mIsRedirect = intval( $data->page_is_redirect );
+ $this->mLatest = intval( $data->page_latest );
// Bug 37225: $latest may no longer match the cached latest Revision object.
// Double-check the ID of any cached latest Revision object for consistency.
if ( $this->mLastRevision && $this->mLastRevision->getId() != $this->mLatest ) {
$this->mTitle->loadFromRow( false );
$this->clearCacheFields();
+
+ $this->mId = 0;
}
$this->mDataLoaded = true;
* @return int Page ID
*/
public function getId() {
- return $this->mTitle->getArticleID();
+ if ( !$this->mDataLoaded ) {
+ $this->loadPageData();
+ }
+ return $this->mId;
}
/**
* @return bool Whether or not the page exists in the database
*/
public function exists() {
- return $this->mTitle->exists();
+ if ( !$this->mDataLoaded ) {
+ $this->loadPageData();
+ }
+ return $this->mId > 0;
}
/**
* @return bool
*/
public function hasViewableContent() {
- return $this->mTitle->exists() || $this->mTitle->isAlwaysKnown();
+ return $this->exists() || $this->mTitle->isAlwaysKnown();
}
/**
return $wgEnableParserCache
&& $parserOptions->getStubThreshold() == 0
- && $this->mTitle->exists()
+ && $this->exists()
&& ( $oldid === null || $oldid === 0 || $oldid === $this->getLatest() )
&& $this->getContentHandler()->isParserCacheSupported();
}
}
// Don't update page view counters on views from bot users (bug 14044)
- if ( !$wgDisableCounters && !$user->isAllowed( 'bot' ) && $this->mTitle->exists() ) {
+ if ( !$wgDisableCounters && !$user->isAllowed( 'bot' ) && $this->exists() ) {
DeferredUpdates::addUpdate( new ViewCountUpdate( $this->getId() ) );
DeferredUpdates::addUpdate( new SiteStatsUpdate( 1, 0, 0 ) );
}
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
// @todo: move this logic to MessageCache
- if ( $this->mTitle->exists() ) {
+ if ( $this->exists() ) {
// NOTE: use transclusion text for messages.
// This is consistent with MessageCache::getMsgFromNamespace()
if ( $affected ) {
$newid = $dbw->insertId();
+ $this->mId = $newid;
$this->mTitle->resetArticleID( $newid );
}
wfProfileOut( __METHOD__ );
*/
function checkFlags( $flags ) {
if ( !( $flags & EDIT_NEW ) && !( $flags & EDIT_UPDATE ) ) {
- if ( $this->mTitle->getArticleID() ) {
+ if ( $this->exists() ) {
$flags |= EDIT_UPDATE;
} else {
$flags |= EDIT_NEW;
$editInfo = $this->prepareContentForEdit( $content, null, $user, $serialisation_format );
$serialized = $editInfo->pst;
$content = $editInfo->pstContent;
- $newsize = $content->getSize();
+ $newsize = $content->getSize();
$dbw = wfGetDB( DB_MASTER );
$now = wfTimestampNow();
}
}
- if ( !$this->mTitle->exists() ) {
+ if ( !$this->exists() ) {
wfProfileOut( __METHOD__ );
return;
}
$restrictionTypes = $this->mTitle->getRestrictionTypes();
- $id = $this->mTitle->getArticleID();
+ $id = $this->getId();
if ( !$cascade ) {
$cascade = false;
// Now that it's safely backed up, delete it
$dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
- $ok = ( $dbw->affectedRows() > 0 ); // getArticleID() uses slave, could be laggy
+ $ok = ( $dbw->affectedRows() > 0 ); // $id could be laggy
if ( !$ok ) {
$dbw->rollback( __METHOD__ );
// Clear caches
WikiPage::onArticleDelete( $this->mTitle );
- // Reset this object
- $this->clear();
-
- // Clear the cached article id so the interface doesn't act like we exist
- $this->mTitle->resetArticleID( 0 );
+ // Reset this object and the Title object
+ $this->loadFromRow( false, self::READ_LATEST );
}
/**
*/
public function getHiddenCategories() {
$result = array();
- $id = $this->mTitle->getArticleID();
+ $id = $this->getId();
if ( $id == 0 ) {
return array();
}
/**
- * Return an applicable autosummary if one exists for the given edit.
- * @param $oldtext String|null: the previous text of the page.
- * @param $newtext String|null: The submitted text of the page.
- * @param $flags Int bitmask: a bitmask of flags submitted for the edit.
- * @return string An appropriate autosummary, or an empty string.
- *
- * @deprecated since 1.21, use ContentHandler::getAutosummary() instead
- */
+ * Return an applicable autosummary if one exists for the given edit.
+ * @param $oldtext String|null: the previous text of the page.
+ * @param $newtext String|null: The submitted text of the page.
+ * @param $flags Int bitmask: a bitmask of flags submitted for the edit.
+ * @return string An appropriate autosummary, or an empty string.
+ *
+ * @deprecated since 1.21, use ContentHandler::getAutosummary() instead
+ */
public static function getAutosummary( $oldtext, $newtext, $flags ) {
// NOTE: stub for backwards-compatibility. assumes the given text is wikitext. will break horribly if it isn't.
}
$dbw->insert( 'category', $insertRows, __METHOD__, 'IGNORE' );
- $addFields = array( 'cat_pages = cat_pages + 1' );
+ $addFields = array( 'cat_pages = cat_pages + 1' );
$removeFields = array( 'cat_pages = cat_pages - 1' );
if ( $ns == NS_CATEGORY ) {
__METHOD__
);
}
+
+ foreach( $added as $catName ) {
+ $cat = Category::newFromName( $catName );
+ wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $this ) );
+ }
+ foreach( $deleted as $catName ) {
+ $cat = Category::newFromName( $catName );
+ wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $this ) );
+ }
}
/**
// are visible.
// Get templates from templatelinks
- $id = $this->mTitle->getArticleID();
+ $id = $this->getId();
$tlTemplates = array();
public static function element( $element, $attribs = null, $contents = '', $allowShortTag = true ) {
$out = '<' . $element;
if( !is_null( $attribs ) ) {
- $out .= self::expandAttributes( $attribs );
+ $out .= self::expandAttributes( $attribs );
}
if( is_null( $contents ) ) {
$out .= '>';
}
/**
- * Generate a form (without the opening form element).
- * Output optionally includes a submit button.
- * @param $fields Array Associative array, key is message corresponding to a description for the field (colon is in the message), value is appropriate input.
- * @param $submitLabel String A message containing a label for the submit button.
- * @return string HTML form.
- */
+ * Generate a form (without the opening form element).
+ * Output optionally includes a submit button.
+ * @param $fields Array Associative array, key is message corresponding to a description for the field (colon is in the message), value is appropriate input.
+ * @param $submitLabel String A message containing a label for the submit button.
+ * @return string HTML form.
+ */
public static function buildForm( $fields, $submitLabel = null ) {
$form = '';
$form .= "<table><tbody>";
*
* Because this class is aimed at verification, an error is raised on
* suspicious or ambiguous input, instead of emulating some standard
- * behaviour.
+ * behavior.
*
* @param $fileName string The archive file name
* @param $callback Array The callback function. It will be called for each file
/**
* Add date selector to quickly get to a certain time
*/
- $year = $request->getInt( 'year' );
- $month = $request->getInt( 'month' );
- $tagFilter = $request->getVal( 'tagfilter' );
+ $year = $request->getInt( 'year' );
+ $month = $request->getInt( 'month' );
+ $tagFilter = $request->getVal( 'tagfilter' );
$tagSelector = ChangeTags::buildTagFilterSelector( $tagFilter );
/**
return $this->mModuleName;
}
-
/**
* Get the module manager, or null if this module has no sub-modules
* @since 1.21
if ( $t === '' ) {
$nothingPrompt = 'Can be empty, or ';
} else {
- $choices[] = $t;
+ $choices[] = $t;
}
}
$desc .= $paramPrefix . $nothingPrompt . $prompt;
*/
/**
-* API module that facilitates the blocking of users. Requires API write mode
-* to be enabled.
-*
+ * API module that facilitates the blocking of users. Requires API write mode
+ * to be enabled.
+ *
* @ingroup API
*/
class ApiBlock extends ApiBase {
if ( !is_null( $params['starttimestamp'] ) && $params['starttimestamp'] != '' ) {
$requestArray['wpStarttime'] = wfTimestamp( TS_MW, $params['starttimestamp'] );
} else {
- $requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime
+ $requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime
}
if ( $params['minor'] || ( !$params['notminor'] && $user->getOption( 'minordefault' ) ) ) {
--- /dev/null
+<?php
+/**
+ *
+ * Created on January 3rd, 2013
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+class ApiImageRotate extends ApiBase {
+
+ private $mPageSet = null;
+
+ public function __construct( $main, $action ) {
+ parent::__construct( $main, $action );
+ }
+
+ /**
+ * Add all items from $values into the result
+ * @param $result array output
+ * @param $values array values to add
+ * @param $flag string the name of the boolean flag to mark this element
+ * @param $name string if given, name of the value
+ */
+ private static function addValues( array &$result, $values, $flag = null, $name = null ) {
+ foreach ( $values as $val ) {
+ if( $val instanceof Title ) {
+ $v = array();
+ ApiQueryBase::addTitleInfo( $v, $val );
+ } elseif( $name !== null ) {
+ $v = array( $name => $val );
+ } else {
+ $v = $val;
+ }
+ if( $flag !== null ) {
+ $v[$flag] = '';
+ }
+ $result[] = $v;
+ }
+ }
+
+
+ public function execute() {
+ $params = $this->extractRequestParams();
+ $rotation = $params[ 'rotation' ];
+ $user = $this->getUser();
+
+ if( is_null( $rotation ) || $rotation % 90 ) {
+ $this->dieUsage( "Rotation: {$rotation}", 'rotation must be multiple of 90 degrees' );
+ }
+
+ $pageSet = $this->getPageSet();
+ $pageSet->execute();
+
+ $result = array();
+ $result = array();
+
+ self::addValues( $result, $pageSet->getInvalidTitles(), 'invalid', 'title' );
+ self::addValues( $result, $pageSet->getSpecialTitles(), 'special', 'title' );
+ self::addValues( $result, $pageSet->getMissingPageIDs(), 'missing', 'pageid' );
+ self::addValues( $result, $pageSet->getMissingRevisionIDs(), 'missing', 'revid' );
+ self::addValues( $result, $pageSet->getMissingTitles(), 'missing' );
+ self::addValues( $result, $pageSet->getInterwikiTitlesAsResult() );
+
+ foreach ( $pageSet->getTitles() as $title ) {
+ $file = wfFindFile( $title );
+
+ $r = array();
+ $r[ 'title' ] = $title->getFullText();
+ if ( !$file ) {
+ $r['missing'] = '';
+ $r['result'] = 'Failure';
+ $result[] = $r;
+ continue;
+ }
+ $handler = $file->getHandler();
+ if ( !$handler || !$handler->canRotate() ) {
+ $r['invalid'] = '';
+ $r['result'] = 'Failure';
+ $result[] = $r;
+ continue;
+ }
+
+ // Check whether we're allowed to rotate this file
+ $this->checkPermissions( $this->getUser(), $file->getTitle() );
+
+ $srcPath = $file->getLocalRefPath();
+ $ext = strtolower( pathinfo( "$srcPath", PATHINFO_EXTENSION ) );
+ $tmpFile = TempFSFile::factory( 'rotate_', $ext);
+ $dstPath = $tmpFile->getPath();
+ $err = $handler->rotate( $file, array(
+ "srcPath" => $srcPath,
+ "dstPath" => $dstPath,
+ "rotation"=> $rotation
+ ) );
+ if ( !$err ) {
+ $comment = wfMessage( 'rotate-comment' )->numParams( $rotation )->text();
+ $status = $file->upload( $dstPath,
+ $comment, $comment, 0, false, false, $this->getUser() );
+ if ( $status->isGood() ) {
+ $r['result'] = 'Success';
+ } else {
+ $r['result'] = 'Failure';
+ $r['errormessage'] = $this->getResult()->convertStatusToArray( $status );
+ }
+ } else {
+ $r['result'] = 'Failure';
+ $r['errormessage'] = $err->toText();
+ }
+ $result[] = $r;
+ }
+ $apiResult = $this->getResult();
+ $apiResult->setIndexedTagName( $result, 'page' );
+ $apiResult->addValue( null, $this->getModuleName(), $result );
+ }
+
+ /**
+ * Get a cached instance of an ApiPageSet object
+ * @return ApiPageSet
+ */
+ private function getPageSet() {
+ if ( $this->mPageSet === null ) {
+ $this->mPageSet = new ApiPageSet( $this, 0, NS_FILE);
+ }
+ return $this->mPageSet;
+ }
+
+ /**
+ * Checks that the user has permissions to perform rotations.
+ * Dies with usage message on inadequate permissions.
+ * @param $user User The user to check.
+ */
+ protected function checkPermissions( $user, $title ) {
+ $permissionErrors = array_merge(
+ $title->getUserPermissionsErrors( 'edit' , $user ),
+ $title->getUserPermissionsErrors( 'upload' , $user )
+ );
+
+ if ( $permissionErrors ) {
+ $this->dieUsageMsg( $permissionErrors[0] );
+ }
+ }
+
+ public function mustBePosted() {
+ return true;
+ }
+
+ public function isWriteMode() {
+ return true;
+ }
+
+ public function getAllowedParams( $flags = 0 ) {
+ $pageSet = $this->getPageSet();
+ $result = array(
+ 'rotation' => array(
+ ApiBase::PARAM_DFLT => 0,
+ ),
+ 'token' => array(
+ ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_REQUIRED => true
+ ),
+ );
+ if ( $flags ) {
+ $result += $this->getPageSet()->getFinalParams( $flags );
+ }
+ return $result;
+ }
+
+ public function getParamDescription() {
+ $pageSet = $this->getPageSet();
+ return $pageSet->getParamDescription() + array(
+ 'rotation' => 'Degrees to rotate image, values can be 0, 90, 180 or 270',
+ 'token' => 'Edit token. You can get one of these through prop=info',
+ );
+ }
+
+ public function getDescription() {
+ return 'Rotate one or more images';
+ }
+
+ public function needsToken() {
+ return true;
+ }
+
+ public function getTokenSalt() {
+ return '';
+ }
+
+ public function getPossibleErrors() {
+ $pageSet = $this->getPageSet();
+ return array_merge(
+ parent::getPossibleErrors(),
+ $pageSet->getPossibleErrors()
+ );
+ }
+
+ public function getExamples() {
+ return array(
+ 'api.php?action=imagerotate&titles=Example.jpg&rotation=90&token=+\\',
+ );
+ }
+}
case LoginForm::ABORTED:
$result['result'] = 'Aborted';
- $result['reason'] = $loginForm->mAbortLoginErrorMsg;
+ $result['reason'] = $loginForm->mAbortLoginErrorMsg;
break;
default:
'import' => 'ApiImport',
'userrights' => 'ApiUserrights',
'options' => 'ApiOptions',
+ 'imagerotate' =>'ApiImageRotate',
);
/**
protected function getCredits() {
return array(
'API developers:',
- ' Roan Kattouw "<Firstname>.<Lastname>@gmail.com" (lead developer Sep 2007-present)',
+ ' Roan Kattouw "<Firstname>.<Lastname>@gmail.com" (lead developer Sep 2007-2009)',
' Victor Vasiliev - vasilvv at gee mail dot com',
' Bryan Tong Minh - bryan . tongminh @ gmail . com',
' Sam Reed - sam @ reedyboy . net',
- ' Yuri Astrakhan "<Firstname><Lastname>@gmail.com" (creator, lead developer Sep 2006-Sep 2007, 2012)',
+ ' Yuri Astrakhan "<Firstname><Lastname>@gmail.com" (creator, lead developer Sep 2006-Sep 2007, 2012-present)',
'',
'Please send your comments, suggestions and questions to mediawiki-api@lists.wikimedia.org',
'or file a bug report at https://bugzilla.wikimedia.org/'
* @param $class ApiFormatBase The class implementing this format.
*/
protected function addFormat( $name, $class ) {
- $this->getModuleManager->addModule( $name, 'format', $class );
+ $this->getModuleManager()->addModule( $name, 'format', $class );
}
/**
*/
/**
-* API module that facilitates the changing of user's preferences.
-* Requires API write mode to be enabled.
-*
+ * API module that facilitates the changing of user's preferences.
+ * Requires API write mode to be enabled.
+ *
* @ingroup API
*/
class ApiOptions extends ApiBase {
$validation = $field->validate( $value, $user->getOptions() );
break;
case 'registered-multiselect':
- // A key for a multiselect option.
+ case 'registered-checkmatrix':
+ // A key for a multiselect or checkmatrix option.
$validation = true;
$value = $value !== null ? (bool) $value : null;
break;
private $mFakePageId = -1;
private $mCacheMode = 'public';
private $mRequestedPageFields = array();
+ private $mDefaultNamespace = NS_MAIN;
/**
* Constructor
* @param $dbSource ApiBase Module implementing getDB().
* Allows PageSet to reuse existing db connection from the shared state like ApiQuery.
* @param $flags int Zero or more flags like DISABLE_GENERATORS
+ * @param $defaultNamespace int the namespace to use if none is specified by a prefix.
* @since 1.21 accepts $flags instead of two boolean values
*/
- public function __construct( ApiBase $dbSource, $flags = 0 ) {
+ public function __construct( ApiBase $dbSource, $flags = 0, $defaultNamespace = NS_MAIN ) {
parent::__construct( $dbSource->getMain(), $dbSource->getModuleName() );
$this->mDbSource = $dbSource;
$this->mAllowGenerator = ( $flags & ApiPageSet::DISABLE_GENERATORS ) == 0;
+ $this->mDefaultNamespace = $defaultNamespace;
$this->profileIn();
$this->mParams = $this->extractRequestParams();
$this->profileDBOut();
}
- $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs
+ $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs
// Resolve any found redirects
$this->resolvePendingRedirects();
* @return LinkBatch
*/
private function processTitlesArray( $titles ) {
- $genderCache = GenderCache::singleton();
- $genderCache->doTitlesArray( $titles, __METHOD__ );
-
+ $usernames = array();
$linkBatch = new LinkBatch();
foreach ( $titles as $title ) {
- $titleObj = is_string( $title ) ? Title::newFromText( $title ) : $title;
+ if ( is_string( $title ) ) {
+ $titleObj = Title::newFromText( $title, $this->mDefaultNamespace );
+ } else {
+ $titleObj = $title;
+ }
if ( !$titleObj ) {
// Handle invalid titles gracefully
- $this->mAllpages[0][$title] = $this->mFakePageId;
+ $this->mAllPages[0][$title] = $this->mFakePageId;
$this->mInvalidTitles[$this->mFakePageId] = $title;
$this->mFakePageId--;
continue; // There's nothing else we can do
}
$unconvertedTitle = $titleObj->getPrefixedText();
$titleWasConverted = false;
- $iw = $titleObj->getInterwiki();
- if ( strval( $iw ) !== '' ) {
+ if ( $titleObj->isExternal() ) {
// This title is an interwiki link.
- $this->mInterwikiTitles[$titleObj->getPrefixedText()] = $iw;
+ $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki();
} else {
// Variants checking
global $wgContLang;
if ( $this->mConvertTitles &&
- count( $wgContLang->getVariants() ) > 1 &&
+ count( $wgContLang->getVariants() ) > 1 &&
!$titleObj->exists() ) {
// Language::findVariantLink will modify titleText and titleObj into
// the canonical variant if possible
} elseif ( is_string( $title ) && $title !== $titleObj->getPrefixedText() ) {
$this->mNormalizedTitles[$title] = $titleObj->getPrefixedText();
}
+
+ // Need gender information
+ if ( MWNamespace::hasGenderDistinction( $titleObj->getNamespace() ) ) {
+ $usernames[] = $titleObj->getText();
+ }
}
+ // Get gender information
+ $genderCache = GenderCache::singleton();
+ $genderCache->doQuery( $usernames, __METHOD__ );
return $linkBatch;
}
// TODO: Does this still need $wgTitle?
global $wgParser, $wgTitle;
- // Currently unnecessary, code to act as a safeguard against any change in current behaviour of uselang
+ // Currently unnecessary, code to act as a safeguard against any change in current behavior of uselang
$oldLang = null;
if ( isset( $params['uselang'] ) && $params['uselang'] != $this->getContext()->getLanguage()->getCode() ) {
$oldLang = $this->getContext()->getLanguage(); // Backup language
if ( count( $params['prtype'] ) || $params['prexpiry'] != 'all' ) {
$this->addTables( 'page_restrictions' );
$this->addWhere( 'page_id=pr_page' );
- $this->addWhere( 'pr_expiry>' . $db->addQuotes( $db->timestamp() ) );
+ $this->addWhere( "pr_expiry > {$db->addQuotes( $db->timestamp() )} OR pr_expiry IS NULL" );
if ( count( $params['prtype'] ) ) {
$this->addWhereFld( 'pr_type', $params['prtype'] );
} elseif ( $params['prfiltercascade'] == 'noncascading' ) {
$this->addWhereFld( 'pr_cascade', 0 );
}
-
- $this->addOption( 'DISTINCT' );
}
$forceNameTitleIndex = false;
$this->addWhere( "pr_expiry != {$db->addQuotes( $db->getInfinity() )}" );
}
+ $this->addOption( 'DISTINCT' );
+
} elseif ( isset( $params['prlevel'] ) ) {
$this->dieUsage( 'prlevel may not be used without prtype', 'params' );
}
$this->addFields( array( 'recentedits' => 'COUNT(*)' ) );
$this->addWhere( 'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes( 'newusers' ) );
- $timestamp = $db->timestamp( wfTimestamp( TS_UNIX ) - $wgActiveUserDays*24*3600 );
+ $timestamp = $db->timestamp( wfTimestamp( TS_UNIX ) - $wgActiveUserDays * 24 * 3600 );
$this->addWhere( 'rc_timestamp >= ' . $db->addQuotes( $timestamp ) );
$this->addOption( 'GROUP BY', $userFieldToSort );
if ( $fld_rights ) {
if ( !isset( $lastUserData['rights'] ) ) {
if ( $lastUserObj ) {
- $lastUserData['rights'] = User::getGroupPermissions( $lastUserObj->getAutomaticGroups() );
+ $lastUserData['rights'] = User::getGroupPermissions( $lastUserObj->getAutomaticGroups() );
} else {
// This should not normally happen
$lastUserData['rights'] = array();
$this->params = $this->extractRequestParams( false );
$this->redirect = isset( $this->params['redirect'] ) && $this->params['redirect'];
$userMax = ( $this->redirect ? ApiBase::LIMIT_BIG1 / 2 : ApiBase::LIMIT_BIG1 );
- $botMax = ( $this->redirect ? ApiBase::LIMIT_BIG2 / 2 : ApiBase::LIMIT_BIG2 );
+ $botMax = ( $this->redirect ? ApiBase::LIMIT_BIG2 / 2 : ApiBase::LIMIT_BIG2 );
$result = $this->getResult();
*/
private function run( $resultPageSet = null ) {
if ( $this->getPageSet()->getGoodTitleCount() == 0 ) {
- return; // nothing to do
+ return; // nothing to do
}
$params = $this->extractRequestParams();
$this->addFieldsIf( 'cl_timestamp', $fld_timestamp || $params['sort'] == 'timestamp' );
- $this->addTables( array( 'page', 'categorylinks' ) ); // must be in this order for 'USE INDEX'
+ $this->addTables( array( 'page', 'categorylinks' ) ); // must be in this order for 'USE INDEX'
$this->addWhereFld( 'cl_to', $categoryTitle->getDBkey() );
$queryTypes = $params['type'];
if ( $mode == 'revs' || $mode == 'user' ) {
// Ignore namespace and unique due to inability to know whether they were purposely set
- foreach( array( 'from', 'to', 'prefix', /*'namespace',*/ 'continue', /*'unique'*/ ) as $p ) {
+ foreach( array( 'from', 'to', 'prefix', /*'namespace', 'unique'*/ ) as $p ) {
if ( !is_null( $params[$p] ) ) {
$this->dieUsage( "The '{$p}' parameter cannot be used in modes 1 or 2", 'badparams' );
}
}
// Check limits
$userMax = $fld_content ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1;
- $botMax = $fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2;
+ $botMax = $fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2;
$limit = $params['limit'];
'namespace' => 'Only list pages in this namespace (3)',
'user' => 'Only list revisions by this user',
'excludeuser' => 'Don\'t list revisions by this user',
- 'continue' => 'When more results are available, use this to continue (3)',
+ 'continue' => 'When more results are available, use this to continue (1, 3)',
'unique' => 'List only one revision for each page (3)',
);
}
array( 'code' => 'badparams', 'info' => "The 'from' parameter cannot be used in modes 1 or 2" ),
array( 'code' => 'badparams', 'info' => "The 'to' parameter cannot be used in modes 1 or 2" ),
array( 'code' => 'badparams', 'info' => "The 'prefix' parameter cannot be used in modes 1 or 2" ),
- array( 'code' => 'badparams', 'info' => "The 'continue' parameter cannot be used in modes 1 or 2" ),
array( 'code' => 'badparams', 'info' => "The 'start' parameter cannot be used in mode 3" ),
array( 'code' => 'badparams', 'info' => "The 'end' parameter cannot be used in mode 3" ),
) );
$query = $params['query'];
$protocol = self::getProtocolPrefix( $params['protocol'] );
- $this->addTables( array( 'page', 'externallinks' ) ); // must be in this order for 'USE INDEX'
+ $this->addTables( array( 'page', 'externallinks' ) ); // must be in this order for 'USE INDEX'
$this->addOption( 'USE INDEX', 'el_index' );
$this->addWhere( 'page_id=el_from' );
$file['suppressed'] = '';
}
-
$fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $file );
if ( !$fit ) {
$this->setContinueEnumParameter( 'continue', $row->fa_name );
*/
private function run( $resultPageSet = null ) {
if ( $this->getPageSet()->getGoodTitleCount() == 0 ) {
- return; // nothing to do
+ return; // nothing to do
}
$params = $this->extractRequestParams();
*/
private function run( $resultPageSet = null ) {
if ( $this->getPageSet()->getGoodTitleCount() == 0 ) {
- return; // nothing to do
+ return; // nothing to do
}
$params = $this->extractRequestParams();
!is_null( $params['endid'] ) || $params['dir'] === 'newer' ||
!is_null( $params['start'] ) || !is_null( $params['end'] ) );
-
$pageSet = $this->getPageSet();
$pageCount = $pageSet->getGoodTitleCount();
$revCount = $pageSet->getRevisionCount();
$index = array();
$userMax = ( $this->fld_content ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1 );
- $botMax = ( $this->fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2 );
+ $botMax = ( $this->fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2 );
$limit = $params['limit'];
if ( $limit == 'max' ) {
$limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
if ( isset( $this->prop['groups'] ) ) {
$vals['groups'] = $user->getEffectiveGroups();
- $result->setIndexedTagName( $vals['groups'], 'g' ); // even if empty
+ $result->setIndexedTagName( $vals['groups'], 'g' ); // even if empty
}
if ( isset( $this->prop['implicitgroups'] ) ) {
$vals['implicitgroups'] = $user->getAutomaticGroups();
- $result->setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
+ $result->setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
}
if ( isset( $this->prop['rights'] ) ) {
// User::getRights() may return duplicate values, strip them
$vals['rights'] = array_values( array_unique( $user->getRights() ) );
- $result->setIndexedTagName( $vals['rights'], 'r' ); // even if empty
+ $result->setIndexedTagName( $vals['rights'], 'r' ); // even if empty
}
if ( isset( $this->prop['changeablegroups'] ) ) {
}
/**
- * Gets all the groups that a user is automatically a member of (implicit groups)
- *
- * @deprecated since 1.20; call User::getAutomaticGroups() directly.
- * @param $user User
- * @return array
- */
+ * Gets all the groups that a user is automatically a member of (implicit groups)
+ *
+ * @deprecated since 1.20; call User::getAutomaticGroups() directly.
+ * @param $user User
+ * @return array
+ */
public static function getAutoGroups( $user ) {
wfDeprecated( __METHOD__, '1.20' );
}
}
-
/**
* Check warnings.
* Returns a suitable array for inclusion into API results if there were warnings
return $warnings;
}
-
/**
* Perform the actual upload. Returns a suitable result array on success;
* dies on failure.
$res = array( 'title' => $title->getPrefixedText() );
- // Currently unnecessary, code to act as a safeguard against any change in current behaviour of uselang
+ // Currently unnecessary, code to act as a safeguard against any change in current behavior of uselang
// Copy from ApiParse
$oldLang = null;
if ( isset( $params['uselang'] ) && $params['uselang'] != $this->getContext()->getLanguage()->getCode() ) {
*/
protected function getPrefix( $table ) {
static $prefixes = array(
- 'pagelinks' => 'pl',
- 'imagelinks' => 'il',
+ 'pagelinks' => 'pl',
+ 'imagelinks' => 'il',
'categorylinks' => 'cl',
'templatelinks' => 'tl',
- 'redirect' => 'rd',
+ 'redirect' => 'rd',
);
if ( isset( $prefixes[$table] ) ) {
case 'templatelinks':
$conds = array(
"{$prefix}_namespace" => $this->title->getNamespace(),
- "{$prefix}_title" => $this->title->getDBkey(),
+ "{$prefix}_title" => $this->title->getDBkey(),
"page_id={$prefix}_from"
);
break;
case 'redirect':
$conds = array(
"{$prefix}_namespace" => $this->title->getNamespace(),
- "{$prefix}_title" => $this->title->getDBkey(),
+ "{$prefix}_title" => $this->title->getDBkey(),
$this->getDb()->makeList( array(
"{$prefix}_interwiki" => '',
"{$prefix}_interwiki IS NULL",
return $cacheEntry['batches'];
}
-
// 4) ... finally fetch from the slow database :(
$this->getLinks( $table );
$cacheEntry = $this->partitionResult( $this->fullResultCache[$table], $batchSize );
}
}
-
/**
* Load a plural XML file with the given filename, compile the relevant
* rules, and save the compiled rules in a process-local cache.
}
/**
- * Get a message from either the content language or the user language.
+ * Get a message from either the content language or the user language. The fallback
+ * language order is the users language fallback union the content language fallback.
+ * This list is then applied to find keys in the following order
+ * 1) MediaWiki:$key/$langcode (for every language except the content language where
+ * we look at MediaWiki:$key)
+ * 2) Built-in messages via the l10n cache which is also in fallback order
*
* @param $key String: the message cache key
- * @param $useDB Boolean: get the message from the DB, false to use only
- * the localisation
- * @param bool|string $langcode Code of the language to get the message for, if
- * it is a valid code create a language for that language,
- * if it is a string but not a valid code then make a basic
- * language object, if it is a false boolean then use the
- * current users language (as a fallback for the old
- * parameter functionality), or if it is a true boolean
- * then use the wikis content language (also as a
- * fallback).
+ * @param $useDB Boolean: If true will look for the message in the DB, false only
+ * get the message from the DB, false to use only the compiled l10n cache.
+ * @param bool|string|object $langcode Code of the language to get the message for.
+ * - If string and a valid code, will create a standard language object
+ * - If string but not a valid code, will create a basic language object
+ * - If boolean and false, create object from the current users language
+ * - If boolean and true, create object from the wikis content language
+ * - If language object, use it as given
* @param $isFullKey Boolean: specifies whether $key is a two part key
* "msg/lang".
*
* @throws MWException
- * @return string|bool
+ * @return string|bool False if the message doesn't exist, otherwise the message
*/
function get( $key, $useDB = true, $langcode = true, $isFullKey = false ) {
global $wgLanguageCode, $wgContLang;
+ wfProfileIn( __METHOD__ );
+
if ( is_int( $key ) ) {
// "Non-string key given" exception sometimes happens for numerical strings that become ints somewhere on their way here
$key = strval( $key );
}
if ( !is_string( $key ) ) {
+ wfProfileOut( __METHOD__ );
throw new MWException( 'Non-string key given' );
}
if ( strval( $key ) === '' ) {
# Shortcut: the empty key is always missing
+ wfProfileOut( __METHOD__ );
return false;
}
- $lang = wfGetLangObj( $langcode );
- if ( !$lang ) {
- throw new MWException( "Bad lang code $langcode given" );
- }
- $langcode = $lang->getCode();
+ # Obtain the initial language object
+ if ( $isFullKey ) {
+ $keyParts = explode( '/', $key );
+ if ( count( $keyParts ) < 2 ) {
+ throw new MWException( "Message key '$key' does not appear to be a full key." );
+ }
- $message = false;
+ $langcode = array_pop( $keyParts );
+ $key = implode( '/', $keyParts );
+ }
+
+ # Obtain a language object for the requested language from the passed language code
+ # Note that the language code could in fact be a language object already but we assume
+ # it's a string further below.
+ $requestedLangObj = wfGetLangObj( $langcode );
+ if ( !$requestedLangObj ) {
+ wfProfileOut( __METHOD__ );
+ throw new MWException( "Bad lang code $langcode given" );
+ }
+ $langcode = $requestedLangObj->getCode();
# Normalise title-case input (with some inlining)
$lckey = str_replace( ' ', '_', $key );
$uckey = $wgContLang->ucfirst( $lckey );
}
+ # Loop through each language in the fallback list until we find something useful
+ $message = false;
+
# Try the MediaWiki namespace
- if( !$this->mDisable && $useDB ) {
- $title = $uckey;
- if( !$isFullKey && ( $langcode != $wgLanguageCode ) ) {
- $title .= '/' . $langcode;
+ if ( !$this->mDisable && $useDB ) {
+ $fallbackChain = Language::getFallbacksIncludingSiteLanguage( $langcode );
+ array_unshift( $fallbackChain, $langcode );
+
+ foreach ( $fallbackChain as $langcode ) {
+ if ( $langcode === $wgLanguageCode ) {
+ # Messages created in the content language will not have the /lang extension
+ $message = $this->getMsgFromNamespace( $uckey, $langcode );
+ } else {
+ $message = $this->getMsgFromNamespace( "$uckey/$langcode", $langcode );
+ }
+
+ if ( $message !== false ) {
+ break;
+ }
}
- $message = $this->getMsgFromNamespace( $title, $langcode );
}
# Try the array in the language object
if ( $message === false ) {
- $message = $lang->getMessage( $lckey );
- if ( is_null( $message ) ) {
+ $message = $requestedLangObj->getMessage( $lckey );
+ if ( is_null ( $message ) ) {
$message = false;
}
}
- # Try the array of another language
+ # If we still have no message, maybe the key was in fact a full key so try that
if( $message === false ) {
$parts = explode( '/', $lckey );
# We may get calls for things that are http-urls from sidebar
}
}
- # Is this a custom message? Try the default language in the db...
- if( ( $message === false || $message === '-' ) &&
- !$this->mDisable && $useDB &&
- !$isFullKey && ( $langcode != $wgLanguageCode ) ) {
- $message = $this->getMsgFromNamespace( $uckey, $wgLanguageCode );
- }
-
# Final fallback
if( $message === false ) {
+ wfProfileOut( __METHOD__ );
return false;
}
' ' => "\xc2\xa0",
) );
+ wfProfileOut( __METHOD__ );
return $message;
}
array( 'page_namespace', 'page_title' ),
array(
'pl_namespace' => $title->getNamespace(),
- 'pl_title' => $title->getDBkey(),
+ 'pl_title' => $title->getDBkey(),
'pl_from=page_id' ),
__METHOD__ );
$blurlArr = $title->getSquidURLs();
throw new MWException( __CLASS__. ' requires the phpredis extension: ' .
'https://github.com/nicolasff/phpredis' );
}
- $this->connectTimeout = isset( $options['connectTimeout'] )
- ? $options['connectTimeout']
- : 1;
- $this->persistent = isset( $options['persistent'] )
- ? $options['persistent']
- : false;
- $this->password = isset( $options['password'] )
- ? $options['password']
- : '';
- $this->poolSize = isset( $options['poolSize'] )
- ? $options['poolSize']
- : 5;
+ $this->connectTimeout = $options['connectTimeout'];
+ $this->persistent = $options['persistent'];
+ $this->password = $options['password'];
+ $this->poolSize = $options['poolSize'];
if ( !isset( $options['serializer'] ) || $options['serializer'] === 'php' ) {
$this->serializer = Redis::SERIALIZER_PHP;
} elseif ( $options['serializer'] === 'igbinary' ) {
}
}
+ /**
+ * @param $options Array
+ * @return Array
+ */
+ protected static function applyDefaultConfig( array $options ) {
+ if ( !isset( $options['connectTimeout'] ) ) {
+ $options['connectTimeout'] = 1;
+ }
+ if ( !isset( $options['persistent'] ) ) {
+ $options['persistent'] = false;
+ }
+ if ( !isset( $options['password'] ) ) {
+ $options['password'] = '';
+ }
+ if ( !isset( $options['poolSize'] ) ) {
+ $options['poolSize'] = 1;
+ }
+ return $options;
+ }
+
/**
* @param $options Array
* @return RedisConnectionPool
*/
public static function singleton( array $options ) {
+ $options = self::applyDefaultConfig( $options );
// Map the options to a unique hash...
$poolOptions = $options;
unset( $poolOptions['poolSize'] ); // avoid pool fragmentation
wfDebug( "Creating a new " . __CLASS__ . " instance with id $id." );
}
// Simply grow the pool size if the existing one is too small
- $psize = isset( $options['poolSize'] ) ? $options['poolSize'] : 1; // size requested
+ $psize = $options['poolSize']; // size requested
self::$instances[$id]->poolSize = max( $psize, self::$instances[$id]->poolSize );
return self::$instances[$id];
return $this->getNativeData() === $that->getNativeData();
}
-
/**
* Returns a list of DataUpdate objects for recording information about this
* Content in some secondary data store.
return $parserOutput->getSecondaryDataUpdates( $title, $recursive );
}
-
/**
* @see Content::getRedirectChain
*
* target is hit in order to provide (hopefully) the Title of the final
* destination instead of another redirect.
*
- * There is usually no need to override the default behaviour, subclasses that
+ * There is usually no need to override the default behavior, subclasses that
* want to implement redirects should override getRedirectTarget().
*
* @since 1.21
* form of the content.
* - If $wgContentHandlerTextFallback is 'ignore' and $content is not a
* TextContent object, this method returns null.
- * - otherwise, the behaviour is undefined.
+ * - otherwise, the behavior is undefined.
*
* @since 1.21
*
return new CssContent( $pst );
}
-
protected function getHtml( ) {
$html = "";
$html .= "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n";
return new JavaScriptContent( $pst );
}
-
protected function getHtml( ) {
$html = "";
$html .= "<pre class=\"mw-code mw-js\" dir=\"ltr\">\n";
return $diff;
}
-
/**
* Returns a generic ParserOutput object, wrapping the HTML returned by
* getHtml().
return new WikitextContent( '' );
}
-
/**
* Returns a WikitextContent object representing a redirect to the given destination page.
*
*/
interface IDBAccessObject {
// Constants for object loading bitfield flags (higher => higher QoS)
- const READ_LATEST = 1; // read from the master
+ const READ_LATEST = 1; // read from the master
const READ_LOCKING = 3; // READ_LATEST and "FOR UPDATE"
// Convenience constant for callers to explicitly request slave data
*/
protected $fileHandle = null;
-
# ------------------------------------------------------------------------------
# Accessors
# ------------------------------------------------------------------------------
* Returns true if this database uses timestamps rather than integers
*
* @return bool
- */
+ */
public function realTimestamps() {
return false;
}
&& in_array( $table, $wgSharedTables ) # A shared table is selected
) {
$database = $wgSharedDB;
- $prefix = $wgSharedPrefix === null ? $this->mTablePrefix : $wgSharedPrefix;
+ $prefix = $wgSharedPrefix === null ? $this->mTablePrefix : $wgSharedPrefix;
} else {
$database = null;
$prefix = $this->mTablePrefix; # Default prefix
$sorry = htmlspecialchars( $this->msg( 'dberr-problems', 'Sorry! This site is experiencing technical difficulties.' ) );
$again = htmlspecialchars( $this->msg( 'dberr-again', 'Try waiting a few minutes and reloading.' ) );
- $info = htmlspecialchars( $this->msg( 'dberr-info', '(Can\'t contact the database server: $1)' ) );
+ $info = htmlspecialchars( $this->msg( 'dberr-info', '(Can\'t contact the database server: $1)' ) );
# No database access
MessageCache::singleton()->disable();
TO $newUser
;
" );
-
-
}
function encodeBlob( $b ) {
parent::reportQueryError( $error, $errno, $sql, $fname, false );
}
-
function queryIgnore( $sql, $fname = 'DatabasePostgres::queryIgnore' ) {
return $this->query( $sql, $fname, true );
}
return $a;
}
-
function indexUnique( $table, $index, $fname = 'DatabasePostgres::indexUnique' ) {
$sql = "SELECT indexname FROM pg_indexes WHERE tablename='{$table}'".
" AND indexdef LIKE 'CREATE UNIQUE%(" .
return '[http://www.postgresql.org/ PostgreSQL]';
}
-
/**
* Return current schema (executes SELECT current_schema())
* Needs transaction
*/
public function lock( $lockName, $method, $timeout = 5 ) {
$key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
- for ( $attempts=1; $attempts <= $timeout; ++$attempts ) {
+ for ( $attempts = 1; $attempts <= $timeout; ++$attempts ) {
$result = $this->query(
"SELECT pg_try_advisory_lock($key) AS lockstatus", $method );
$row = $this->fetchObject( $result );
* @return bool
*/
function wasErrorReissuable() {
- return $this->lastErrno() == 17; // SQLITE_SCHEMA;
+ return $this->lastErrno() == 17; // SQLITE_SCHEMA;
}
/**
return $this->query( $sql, $fname );
}
-
/**
* List all tables on the database
*
* doesn't go anywhere near an actual database.
*/
class FakeResultWrapper extends ResultWrapper {
- var $result = array();
- var $db = null; // And it's going to stay that way :D
- var $pos = 0;
+ var $result = array();
+ var $db = null; // And it's going to stay that way :D
+ var $pos = 0;
var $currentRow = null;
function __construct( $array ) {
interface IORMRow {
-
/**
* Constructor.
*
*/
public function setReadDb( $db );
-
/**
* Get the ID of the any foreign wiki to use as a target for database operations
*
* @ingroup Database
*/
-
/**
* A multi-wiki, multi-master factory for Wikimedia and similar installations.
* Ignores the old configuration globals
$this->mServers[$i]['slave pos'] = $conn->getSlavePos();
}
}
- if ( $this->mReadIndex <=0 && $this->mLoads[$i]>0 && $i !== false ) {
+ if ( $this->mReadIndex <= 0 && $this->mLoads[$i] > 0 && $i !== false ) {
$this->mReadIndex = $i;
}
}
$value = (float)$value;
break;
case 'bool':
- if ( is_string( $value ) ) {
- $value = $value !== '0';
- } elseif ( is_int( $value ) ) {
- $value = $value !== 0;
- }
+ $value = (bool)$value;
break;
case 'array':
if ( is_string( $value ) ) {
* @return ORMResult
*/
public function select( $fields = null, array $conditions = array(),
- array $options = array(), $functionName = null ) {
+ array $options = array(), $functionName = null ) {
$res = $this->rawSelect( $fields, $conditions, $options, $functionName );
return new ORMResult( $this, $res );
}
* @throws DBQueryError if the query failed (even if the database was in ignoreErrors mode).
*/
public function selectObjects( $fields = null, array $conditions = array(),
- array $options = array(), $functionName = null ) {
+ array $options = array(), $functionName = null ) {
$result = $this->selectFields( $fields, $conditions, $options, false, $functionName );
$objects = array();
* @throws DBQueryError if the quey failed (even if the database was in ignoreErrors mode).
*/
public function rawSelect( $fields = null, array $conditions = array(),
- array $options = array(), $functionName = null ) {
+ array $options = array(), $functionName = null ) {
if ( is_null( $fields ) ) {
$fields = array_keys( $this->getFields() );
}
* @return array of array
*/
public function selectFields( $fields = null, array $conditions = array(),
- array $options = array(), $collapse = true, $functionName = null ) {
+ array $options = array(), $collapse = true, $functionName = null ) {
$objects = array();
$result = $this->rawSelect( $fields, $conditions, $options, $functionName );
trigger_error( "Reversed closing doesn't match", E_USER_ERROR );
}
-
$prevtype = 'none';
foreach ( $this->edits as $edit ) {
if ( $prevtype == $edit->type ) {
return $this->msg( 'lineno' )->numParams( $matches[1] )->escaped();
}
-
/**
* If there are revisions between the ones being compared, return a note saying so.
* @return string
$temp = array( 0, 0, 0 );
-
$max_progress = array_fill( 0, ceil( max( $forward_end_diag - $forward_start_diag,
$backward_end_diag - $backward_start_diag ) / 2 ), $temp );
$num_progress = 0; // the 1st entry is current, it is initialized
if ( isset( $config['containerPaths'] ) ) {
$this->containerPaths = (array)$config['containerPaths'];
foreach ( $this->containerPaths as &$path ) {
- $path = rtrim( $path, '/' ); // remove trailing slash
+ $path = rtrim( $path, '/' ); // remove trailing slash
}
}
* @param $params Array
* $params include:
* - src : source storage path
+ * - ttl : lifetime (seconds) if pre-authenticated; default is 1 day
* @return string|null
* @since 1.21
*/
$mBackend = $this->backends[$this->masterIndex];
foreach ( $paths as $path ) {
- $mPath = $this->substPaths( $path, $mBackend );
- $mSha1 = $mBackend->getFileSha1Base36( array( 'src' => $mPath ) );
+ $mPath = $this->substPaths( $path, $mBackend );
+ $mSha1 = $mBackend->getFileSha1Base36( array( 'src' => $mPath ) );
$mExist = $mBackend->fileExists( array( 'src' => $mPath ) );
// Check if the master backend is available...
if ( $mExist === null ) {
*/
public function __construct( array $config ) {
parent::__construct( $config );
- $this->memCache = new EmptyBagOStuff(); // disabled by default
- $this->cheapCache = new ProcessCacheLRU( 300 );
+ $this->memCache = new EmptyBagOStuff(); // disabled by default
+ $this->cheapCache = new ProcessCacheLRU( 300 );
$this->expensiveCache = new ProcessCacheLRU( 5 );
}
$res = '';
foreach ( explode( ';', $disposition ) as $part ) {
$part = trim( $part );
- $new = ( $res === '' ) ? $part : "{$res};{$part}";
+ $new = ( $res === '' ) ? $part : "{$res};{$part}";
if ( strlen( $new ) <= 255 ) {
$res = $new;
} else {
return null; // invalid path
}
try {
+ $ttl = isset( $params['ttl'] ) ? $params['ttl'] : 86400;
$sContObj = $this->getContainer( $srcCont );
$obj = new CF_Object( $sContObj, $srcRel, false, false ); // skip HEAD
if ( $this->swiftTempUrlKey != '' ) {
- return $obj->get_temp_url( $this->swiftTempUrlKey, 86400, "GET" );
+ return $obj->get_temp_url( $this->swiftTempUrlKey, $ttl, "GET" );
} else { // give S3 API URL for rgw
- $expires = time() + 86400;
+ $expires = time() + $ttl;
// Path for signature starts with the bucket
$spath = '/' . rawurlencode( $srcCont ) . '/' .
str_replace( '%2F', '/', rawurlencode( $srcRel ) );
return $result;
}
+ /**
+ * Return an array of files where the name starts with $prefix.
+ *
+ * STUB
+ * @param string $prefix The prefix to search for
+ * @param int $limit The maximum amount of files to return
+ * @return array
+ */
+ public function findFilesByPrefix( $prefix, $limit ) {
+ return array();
+ }
+
/**
* Get the public root URL of the repository
*
throw new MWException( 'Validation error in $dstRel' );
}
$dstPath = "$root/$dstRel";
- $dstDir = dirname( $dstPath );
+ $dstDir = dirname( $dstPath );
// Create destination directories for this triplet
if ( !$this->initDirectory( $dstDir )->isOK() ) {
return $this->newFatal( 'directorycreateerror', $dstDir );
public function storeTemp( $originalName, $srcPath ) {
$this->assertWritableRepo(); // fail out if read-only
- $date = gmdate( "YmdHis" );
- $hashPath = $this->getHashPath( $originalName );
- $dstRel = "{$hashPath}{$date}!{$originalName}";
- $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $originalName );
+ $date = gmdate( "YmdHis" );
+ $hashPath = $this->getHashPath( $originalName );
+ $dstRel = "{$hashPath}{$date}!{$originalName}";
+ $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $originalName );
$virtualUrl = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;
$result = $this->quickImport( $srcPath, $virtualUrl );
*/
public function nameForThumb( $name ) {
if ( strlen( $name ) > $this->abbrvThreshold ) {
- $ext = FileBackend::extensionFromPath( $name );
+ $ext = FileBackend::extensionFromPath( $name );
$name = ( $ext == '' ) ? 'thumbnail' : "thumbnail.$ext";
}
return $name;
return false;
}
-
# @todo FIXME: Delete old thumbs that aren't being used. Maintenance script?
$backend->prepare( array( 'dir' => dirname( $localFilename ) ) );
$params = array( 'dst' => $localFilename, 'content' => $thumb );
$expiry = 86400; // has invalidation, 1 day
}
$cachedValue = $wgMemc->get( $memcKey );
- if ( $cachedValue === ' ' || $cachedValue === '' ) {
+ if ( $cachedValue === ' ' || $cachedValue === '' ) {
// Does not exist
return false;
} elseif ( strval( $cachedValue ) !== '' ) {
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey(),
),
- __METHOD__ //Function name
+ __METHOD__ //Function name
);
return $id;
}
return $result;
}
+ /**\r
+ * Return an array of files where the name starts with $prefix.\r
+ *\r
+ * @param string $prefix The prefix to search for\r
+ * @param int $limit The maximum amount of files to return\r
+ * @return array\r
+ */\r
+ public function findFilesByPrefix( $prefix, $limit ) {
+ $selectOptions = array( 'ORDER BY' => 'img_name', 'LIMIT' => intval( $limit ) );
+
+ // Query database\r
+ $dbr = $this->getSlaveDB();
+ $res = $dbr->select(
+ 'image',
+ LocalFile::selectFields(),
+ 'img_name ' . $dbr->buildLike( $prefix, $dbr->anyString() ),
+ __METHOD__,
+ $selectOptions
+ );
+
+ // Build file objects
+ $files = array();
+ foreach ( $res as $row ) {
+ $files[] = $this->newFileFromRow( $row );
+ }
+ return $files;\r
+ }
+
/**
* Get a connection to the slave DB
* @return DatabaseBase
FileRepo, where no such configuration is needed.
File objects are generated by a factory function from the repository. The
-repository thus has full control over the behaviour of its subsidiary file
+repository thus has full control over the behavior of its subsidiary file
class, since it can subclass the file class and override functionality at its
whim. Thus there is no need for the File subclass to query its parent repository
-for information about repository-class-dependent behaviour -- the file subclass
+for information about repository-class-dependent behavior -- the file subclass
is generally fully aware of the static preferences of its repository. Limited
exceptions can be made to this rule to permit sharing of functions, or perhaps
even entire classes, between repositories.
* returns false.
*
* @return string|bool ForeignAPIFile::getPath can return false
- */
+ */
public function getPath() {
if ( !isset( $this->path ) ) {
$this->assertRepoDefined();
}
/**
- * get versioned metadata
- *
- * @param $metadata Mixed Array or String of (serialized) metadata
- * @param $version integer version number.
- * @return Array containing metadata, or what was passed to it on fail (unserializing if not array)
- */
+ * get versioned metadata
+ *
+ * @param $metadata Mixed Array or String of (serialized) metadata
+ * @param $version integer version number.
+ * @return Array containing metadata, or what was passed to it on fail (unserializing if not array)
+ */
public function convertMetadataVersion($metadata, $version) {
$handler = $this->getHandler();
if ( !is_array( $metadata ) ) {
* @return string
*/
function getDescriptionUrl() {
- // Restore remote behaviour
+ // Restore remote behavior
return File::getDescriptionUrl();
}
* @return string
*/
function getDescriptionText() {
- // Restore remote behaviour
+ // Restore remote behavior
return File::getDescriptionText();
}
}
// If the cache value gets to large it will not fit in memcached and nothing will
// get cached at all, causing master queries for any file access.
foreach ( $this->getLazyCacheFields( '' ) as $field ) {
- if ( isset( $cache[$field] ) && strlen( $cache[$field] ) > 100*1024 ) {
+ if ( isset( $cache[$field] ) && strlen( $cache[$field] ) > 100 * 1024 ) {
unset( $cache[$field] ); // don't let the value get too big
}
}
*/
function getMoveTriplets() {
$moves = array_merge( array( $this->cur ), $this->olds );
- $triplets = array(); // The format is: (srcUrl, destZone, destUrl)
+ $triplets = array(); // The format is: (srcUrl, destZone, destUrl)
foreach ( $moves as $move ) {
// $move: (oldRelativePath, newRelativePath)
However, MediaWiki requires PHP $2 or higher.',
'config-unicode-using-utf8' => 'Using Brion Vibber\'s utf8_normalize.so for Unicode normalization.',
'config-unicode-using-intl' => 'Using the [http://pecl.php.net/intl intl PECL extension] for Unicode normalization.',
- 'config-unicode-pure-php-warning' => "'''Warning''': The [http://pecl.php.net/intl intl PECL extension] is not available to handle Unicode normalization, falling back to slow pure-PHP implementation.
+ 'config-unicode-pure-php-warning' => "'''Warning:''' The [http://pecl.php.net/intl intl PECL extension] is not available to handle Unicode normalization, falling back to slow pure-PHP implementation.
If you run a high-traffic site, you should read a little on [//www.mediawiki.org/wiki/Unicode_normalization_considerations Unicode normalization].",
- 'config-unicode-update-warning' => "'''Warning''': The installed version of the Unicode normalization wrapper uses an older version of [http://site.icu-project.org/ the ICU project's] library.
+ 'config-unicode-update-warning' => "'''Warning:''' The installed version of the Unicode normalization wrapper uses an older version of [http://site.icu-project.org/ the ICU project's] library.
You should [//www.mediawiki.org/wiki/Unicode_normalization_considerations upgrade] if you are at all concerned about using Unicode.",
'config-no-db' => 'Could not find a suitable database driver! You need to install a database driver for PHP.
The following database types are supported: $1.
If you are on shared hosting, ask your hosting provider to install a suitable database driver.
If you compiled PHP yourself, reconfigure it with a database client enabled, for example using <code>./configure --with-mysql</code>.
If you installed PHP from a Debian or Ubuntu package, then you also need install the php5-mysql module.',
- 'config-outdated-sqlite' => "'''Warning''': you have SQLite $1, which is lower than minimum required version $2. SQLite will be unavailable.",
- 'config-no-fts3' => "'''Warning''': SQLite is compiled without the [//sqlite.org/fts3.html FTS3 module], search features will be unavailable on this backend.",
+ 'config-outdated-sqlite' => "'''Warning:''' you have SQLite $1, which is lower than minimum required version $2. SQLite will be unavailable.",
+ 'config-no-fts3' => "'''Warning:''' SQLite is compiled without the [//sqlite.org/fts3.html FTS3 module], search features will be unavailable on this backend.",
'config-register-globals' => "'''Warning: PHP's <code>[http://php.net/register_globals register_globals]</code> option is enabled.'''
'''Disable it if you can.'''
MediaWiki will work, but your server is exposed to potential security vulnerabilities.",
If you're running Mandrake, install the php-xml package.",
'config-pcre' => 'The PCRE support module appears to be missing.
MediaWiki requires the Perl-compatible regular expression functions to work.',
- 'config-pcre-no-utf8' => "'''Fatal''': PHP's PCRE module seems to be compiled without PCRE_UTF8 support.
+ 'config-pcre-no-utf8' => "'''Fatal:''' PHP's PCRE module seems to be compiled without PCRE_UTF8 support.
MediaWiki requires UTF-8 support to function correctly.",
'config-memory-raised' => "PHP's <code>memory_limit</code> is $1, raised to $2.",
'config-memory-bad' => "'''Warning:''' PHP's <code>memory_limit</code> is $1.
This is probably too low.
The installation may fail!",
- 'config-ctype' => "'''Fatal''': PHP must be compiled with support for the [http://www.php.net/manual/en/ctype.installation.php Ctype extension].",
+ 'config-ctype' => "'''Fatal:''' PHP must be compiled with support for the [http://www.php.net/manual/en/ctype.installation.php Ctype extension].",
'config-xcache' => '[http://xcache.lighttpd.net/ XCache] is installed',
'config-apc' => '[http://www.php.net/apc APC] is installed',
'config-wincache' => '[http://www.iis.net/download/WinCacheForPhp WinCache] is installed',
'config-no-cache' => "'''Warning:''' Could not find [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] or [http://www.iis.net/download/WinCacheForPhp WinCache].
Object caching is not enabled.",
- 'config-mod-security' => "'''Warning''': Your web server has [http://modsecurity.org/ mod_security] enabled. If misconfigured, it can cause problems for MediaWiki or other software that allows users to post arbitrary content.
+ 'config-mod-security' => "'''Warning:''' Your web server has [http://modsecurity.org/ mod_security] enabled. If misconfigured, it can cause problems for MediaWiki or other software that allows users to post arbitrary content.
Refer to [http://modsecurity.org/documentation/ mod_security documentation] or contact your host's support if you encounter random errors.",
'config-diff3-bad' => 'GNU diff3 not found.',
'config-imagemagick' => 'Found ImageMagick: <code>$1</code>.
Image thumbnailing will be disabled.',
'config-no-uri' => "'''Error:''' Could not determine the current URI.
Installation aborted.",
- 'config-no-cli-uri' => "'''Warning''': No --scriptpath specified, using default: <code>$1</code>.",
+ 'config-no-cli-uri' => "'''Warning:''' No --scriptpath specified, using default: <code>$1</code>.",
'config-using-server' => 'Using server name "<nowiki>$1</nowiki>".',
'config-using-uri' => 'Using server URL "<nowiki>$1$2</nowiki>".',
'config-uploads-not-safe' => "'''Warning:''' Your default directory for uploads <code>$1</code> is vulnerable to arbitrary scripts execution.
You can now [$1 start using your wiki].",
'config-regenerate' => 'Regenerate <code>LocalSettings.php</code> →',
'config-show-table-status' => '<code>SHOW TABLE STATUS</code> query failed!',
- 'config-unknown-collation' => "'''Warning:''' Database is using unrecognised collation.",
+ 'config-unknown-collation' => "'''Warning:''' Database is using unrecognized collation.",
'config-db-web-account' => 'Database account for web access',
'config-db-web-help' => 'Select the username and password that the web server will use to connect to the database server, during ordinary operation of the wiki.',
'config-db-web-account-same' => 'Use the same account as for installation',
'config-mysql-engine' => 'Storage engine:',
'config-mysql-innodb' => 'InnoDB',
'config-mysql-myisam' => 'MyISAM',
- 'config-mysql-myisam-dep' => "'''Warning''': You have selected MyISAM as storage engine for MySQL, which is not recommended for use with MediaWiki, because:
+ 'config-mysql-myisam-dep' => "'''Warning:''' You have selected MyISAM as storage engine for MySQL, which is not recommended for use with MediaWiki, because:
* it barely supports concurrency due to table locking
* it is more prone to corruption than other engines
* the MediaWiki codebase does not always handle MyISAM as it should
'config-install-user-missing-create' => 'The specified user "$1" does not exist.
Please click the "create account" checkbox below if you want to create it.',
'config-install-tables' => 'Creating tables',
- 'config-install-tables-exist' => "'''Warning''': MediaWiki tables seem to already exist.
+ 'config-install-tables-exist' => "'''Warning:''' MediaWiki tables seem to already exist.
Skipping creation.",
- 'config-install-tables-failed' => "'''Error''': Table creation failed with the following error: $1",
+ 'config-install-tables-failed' => "'''Error:''' Table creation failed with the following error: $1",
'config-install-interwiki' => 'Populating default interwiki table',
'config-install-interwiki-list' => 'Could not read file <code>interwiki.list</code>.',
- 'config-install-interwiki-exists' => "'''Warning''': The interwiki table seems to already have entries.
+ 'config-install-interwiki-exists' => "'''Warning:''' The interwiki table seems to already have entries.
Skipping default list.",
'config-install-stats' => 'Initializing statistics',
'config-install-keys' => 'Generating secret keys',
$3
-'''Note''': If you do not do this now, this generated configuration file will not be available to you later if you exit the installation without downloading it.
+'''Note:''' If you do not do this now, this generated configuration file will not be available to you later if you exit the installation without downloading it.
When that has been done, you can '''[$2 enter your wiki]'''.",
'config-download-localsettings' => 'Download <code>LocalSettings.php</code>',
'mainpagedocfooter' => 'Περισσότερες πληροφορίες σχετικά με τη χρήση και με τη ρύθμιση παραμέτρων θα βρείτε στους συνδέσμους: [//meta.wikimedia.org/wiki/MediaWiki_localisation Οδηγίες για τροποποίηση του περιβάλλοντος εργασίας] και [//meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide Εγχειρίδιο χρήστη].', # Fuzzy
);
+/** British English (British English)
+ * @author Shirayuki
+ */
+$messages['en-gb'] = array(
+ 'config-unicode-using-utf8' => "Using Brion Vibber's utf8_normalize.so for Unicode normalisation.",
+ 'config-unicode-using-intl' => 'Using the [http://pecl.php.net/intl intl PECL extension] for Unicode normalisation.',
+ 'config-unicode-pure-php-warning' => "'''Warning:''' The [http://pecl.php.net/intl intl PECL extension] is not available to handle Unicode normalisation, falling back to slow pure-PHP implementation.
+If you run a high-traffic site, you should read a little on [//www.mediawiki.org/wiki/Unicode_normalization_considerations Unicode normalisation].",
+ 'config-unicode-update-warning' => "'''Warning:''' The installed version of the Unicode normalisation wrapper uses an older version of [http://site.icu-project.org/ the ICU project's] library.
+You should [//www.mediawiki.org/wiki/Unicode_normalization_considerations upgrade] if you are at all concerned about using Unicode.",
+ 'config-unknown-collation' => "'''Warning:''' Database is using unrecognised collation.",
+ 'config-profile-fishbowl' => 'Authorised editors only',
+ 'config-install-stats' => 'Initialising statistics',
+);
+
/** Esperanto (Esperanto)
* @author Airon90
* @author Yekrats
しかし、MediaWikiには PHP $2 以上が必要です。',
'config-unicode-using-utf8' => 'Unicode正規化に、Brion Vibberのutf8_normalize.soを使用。',
'config-unicode-using-intl' => 'Unicode正規化に[http://pecl.php.net/intl intl PECL 拡張機能]を使用。',
- 'config-unicode-pure-php-warning' => "'''警告''': Unicode 正規化の処理に [http://pecl.php.net/intl intl PECL 拡張機能]を利用できないため、処理が遅いピュア PHP の実装を代わりに使用しています。
+ 'config-unicode-pure-php-warning' => "'''警告:''' Unicode 正規化の処理に [http://pecl.php.net/intl intl PECL 拡張機能]を利用できないため、処理が遅いピュア PHP の実装を代わりに使用しています。
高トラフィックのサイトを運営する場合は、[//www.mediawiki.org/wiki/Unicode_normalization_considerations Unicode 正規化]をお読みください。",
- 'config-unicode-update-warning' => "'''警告''': インストールされているバージョンの Unicode 正規化ラッパーは、[http://site.icu-project.org/ ICU プロジェクト]のライブラリの古いバージョンを使用しています。
+ 'config-unicode-update-warning' => "'''警告:''' インストールされているバージョンの Unicode 正規化ラッパーは、[http://site.icu-project.org/ ICU プロジェクト]のライブラリの古いバージョンを使用しています。
Unicode を少しでも利用する可能性がある場合は、[//www.mediawiki.org/wiki/Unicode_normalization_considerations アップグレード]してください。",
'config-no-db' => '適切なデータベース ドライバーが見つかりませんでした! PHP にデータベース ドライバーをインストールする必要があります。
以下の種類のデータベースに対応しています: $1
共有サーバーを使用している場合は、適切なデータベース ドライバーのインストールを、サーバーの管理者に依頼してください。
PHP を自分でコンパイルした場合は、例えば <code>./configure --with-mysql</code> を実行して、データベース クライアントを使用できるように再設定してください。
Debian または Ubuntu のパッケージから PHP をインストールした場合は、php5-mysql モジュールもインストールする必要があります。',
- 'config-no-fts3' => "'''警告''': SQLite は [//sqlite.org/fts3.html FTS3] モジュールなしでコンパイルされており、このバックエンドでは検索機能は利用できなくなります。",
+ 'config-no-fts3' => "'''警告:''' SQLite は [//sqlite.org/fts3.html FTS3] モジュールなしでコンパイルされており、このバックエンドでは検索機能は利用できなくなります。",
'config-register-globals' => "'''警告: PHP の <code>[http://php.net/register_globals register_globals]</code> オプションが有効になっています。'''
'''可能なら無効化してください。'''
MediaWiki は動作しますが、サーバーの潜在的なセキュリティ脆弱性が露呈されます。",
Mandrakeを実行している場合、php-xmlパッケージをインストールしてください。',
'config-pcre' => 'PCREをサポートしているモジュールが不足しているようです。
MediaWikiは、Perl互換の正規表現関数の動作が必要です。',
- 'config-pcre-no-utf8' => "'''致命的エラー''': PHP の PCRE が PCRE_UTF8 対応なしでコンパイルされているようです。
+ 'config-pcre-no-utf8' => "'''致命的エラー:''' PHP の PCRE が PCRE_UTF8 対応なしでコンパイルされているようです。
MediaWiki を正しく動作させるには、UTF-8 対応が必要です。",
'config-memory-raised' => 'PHPの<code>memory_limit</code>は$1で、$2に引き上げられました。',
'config-memory-bad' => "'''警告:''' PHPの<code>memory_limit</code>に$1に設定されています。
画像のサムネイル生成は無効になります。',
'config-no-uri' => "'''エラー:''' 現在のURIを決定できませんでした。
インストールは中止されました。",
- 'config-no-cli-uri' => "'''警告''': --scriptpath が指定されていないため、既定値 <code>$1</code> を使用します。",
+ 'config-no-cli-uri' => "'''警告:''' --scriptpath が指定されていないため、既定値 <code>$1</code> を使用します。",
'config-using-server' => 'サーバー名「<nowiki>$1</nowiki>」を使用しています。',
'config-using-uri' => 'サーバー URL「<nowiki>$1$2</nowiki>」を使用しています。',
'config-uploads-not-safe' => "'''警告:''' アップロードの既定ディレクトリ <code>$1</code> に、任意のスクリプト実行に関する脆弱性があります。
'config-install-user-missing-create' => '指定したユーザー「$1」は存在しません。
アカウントを作成する場合は、下の「アカウント作成」をクリックしてください。',
'config-install-tables' => 'テーブルの作成',
- 'config-install-tables-exist' => "'''警告''': MediaWiki テーブルは既に存在するようです。
+ 'config-install-tables-exist' => "'''警告:''' MediaWiki テーブルは既に存在するようです。
作成を省略します。",
- 'config-install-tables-failed' => "'''エラー''': テーブルの作成が、以下のエラーにより失敗しました: $1",
+ 'config-install-tables-failed' => "'''エラー:''' テーブルの作成が、以下のエラーにより失敗しました: $1",
'config-install-interwiki' => '既定のウィキ間テーブルの導入',
'config-install-interwiki-list' => 'ファイル <code>interwiki.list</code> から読み取れませんでした。',
- 'config-install-interwiki-exists' => "'''警告''': ウィキ間テーブルは既に登録されているようです。
+ 'config-install-interwiki-exists' => "'''警告:''' ウィキ間テーブルは既に登録されているようです。
既定のテーブルを無視します。",
'config-install-stats' => '統計情報の初期化',
'config-install-keys' => '秘密鍵の生成',
$3
-'''注意''': この生成された設定ファイルをダウンロードせずにインストールを終了すると、このファイルは利用できなくなります。
+'''注意:''' この生成された設定ファイルをダウンロードせずにインストールを終了すると、このファイルは利用できなくなります。
上記の作業が完了すると、'''[$2 ウィキに入る]'''ことができます。",
'config-download-localsettings' => '<code>LocalSettings.php</code> をダウンロード',
* @author පසිඳු කාවින්ද
*/
$messages['yi'] = array(
+ 'config-desc' => 'דער אינסטאלירער פאר מעדיעוויקי',
+ 'config-title' => 'מעדיעוויקי $1 אינסטאלירונג',
'config-information' => 'אינפֿארמאציע',
+ 'config-wiki-language' => 'ווקי שפראך:',
'config-back' => '→ צוריק',
'config-continue' => 'פֿארזעצן ←',
'config-page-language' => 'שפראַך',
'config-env-php-toolow' => '已安装PHP $1;但是,MediaWiki需要PHP $2或更高版本。',
'config-unicode-using-utf8' => '使用Brion Vibber的utf8_normalize.so实现Unicode正常化。',
'config-unicode-using-intl' => '使用[http://pecl.php.net/intl intl PECL扩展]实现Unicode正常化。',
- 'config-unicode-pure-php-warning' => "'''警告''':因为尚未安装 [http://pecl.php.net/intl intl PECL 扩展]以处理 Unicode 正常化,故只能退而采用运行较慢的纯 PHP 实现的方法。
+ 'config-unicode-pure-php-warning' => "'''警告:'''因为尚未安装 [http://pecl.php.net/intl intl PECL 扩展]以处理 Unicode 正常化,故只能退而采用运行较慢的纯 PHP 实现的方法。
如果您运行着一个高流量的站点,请参阅 [//www.mediawiki.org/wiki/Unicode_normalization_considerations Unicode 正常化]一文。",
'config-unicode-update-warning' => "'''警告''':Unicode正常化封装器的已安装版本使用了旧版本的[http://site.icu-project.org/ ICU项目]库。如果您需要使用Unicode,请将其[//www.mediawiki.org/wiki/Unicode_normalization_considerations 升级]。",
'config-no-db' => '找不到合适的数据库驱动!您需要为PHP安装数据库驱动。目前支持以下数据库:$1。
请考虑将数据库统一放置在某处,如<code>/var/lib/mediawiki/yourwiki</code>下。",
'config-oracle-def-ts' => '默认表空间:',
'config-oracle-temp-ts' => '临时表空间:',
- 'config-type-ibm_db2' => 'IBM DB2',
'config-support-info' => 'MediaWiki支持以下数据库系统:
$1
'config-support-postgres' => '* $1是一种流行的开源数据库系统,可作为MySQL的替代([http://www.php.net/manual/en/pgsql.installation.php 如何将对PostgreSQL的支持编译进PHP中])。本程序中可能依然存在一些小而明显的错误,因此并不建议在生产环境中使用该数据库系统。',
'config-support-sqlite' => '* $1是一种轻量级的数据库系统,能被良好地支持。([http://www.php.net/manual/en/pdo.installation.php 如何将对SQLite的支持编译进PHP中],须使用PDO)',
'config-support-oracle' => '* $1是一种商用企业级的数据库。([http://www.php.net/manual/en/oci8.installation.php 如何将对OCI8的支持编译进PHP中])',
- 'config-support-ibm_db2' => '* $1是一种商用企业级数据库。([http://www.php.net/manual/en/ibm-db2.installation.php 如何编译支持IBM DB2的PHP])',
'config-header-mysql' => 'MySQL设置',
'config-header-postgres' => 'PostgreSQL设置',
'config-header-sqlite' => 'SQLite设置',
'config-header-oracle' => 'Oracle设置',
- 'config-header-ibm_db2' => 'IBM DB2设置',
'config-invalid-db-type' => '无效的数据库类型',
'config-missing-db-name' => '您必须为“数据库名称”输入内容',
'config-missing-db-host' => '您必须为“数据库主机”输入内容',
'config-mysql-charset-help' => "在'''二进制模式'''下,MediaWiki会将UTF-8编码的文本存于数据库的二进制字段中。相对于MySQL的UTF-8模式,这种方法效率更高,并允许您使用全范围的Unicode字符。
在'''UTF-8模式'''下,MySQL将知道您数据使用的字符集,并能适当地提供和转换内容。但这样做您将无法在数据库中存储[//zh.wikipedia.org/wiki/基本多文种平面 基本多文种平面]以外的字符。",
- 'config-ibm_db2-low-db-pagesize' => "您的DB2数据库默认表空间的页长(pagesize)不足。至少需要'''32K'''或更大的页长。",
'config-site-name' => 'Wiki的名称:',
'config-site-name-help' => '填入的内容会出现在浏览器的标题栏以及其他多处位置中。',
'config-site-name-blank' => '输入网站的名称。',
'config-env-php-toolow' => '已安裝 PHP $1;但是,MediaWiki 需要 PHP $2 或更高版本。',
'config-unicode-using-utf8' => '將使用 Brion Vibber 的 utf8_normalize.so 以實作 Unicode 正規化。',
'config-unicode-using-intl' => '將使用 [http://pecl.php.net/intl intl PECL 延伸函式庫]以實作 Unicode 正規化。',
- 'config-unicode-pure-php-warning' => "'''警告''':因為尚未安裝 [http://pecl.php.net/intl intl PECL 延伸函式庫]以處理 Unicode 正規化,故只能退而採用較慢的純 PHP 實作。如果您運行着一個高流量的網站,請參閱 [//www.mediawiki.org/wiki/Unicode_normalization_considerations Unicode 正規化]一文。",
+ 'config-unicode-pure-php-warning' => "'''警告:'''因為尚未安裝 [http://pecl.php.net/intl intl PECL 延伸函式庫]以處理 Unicode 正規化,故只能退而採用較慢的純 PHP 實作。如果您運行着一個高流量的網站,請參閱 [//www.mediawiki.org/wiki/Unicode_normalization_considerations Unicode 正規化]一文。",
'config-unicode-update-warning' => "'''警告''':Unicode正常化封裝器的已安裝版本使用了舊版本的[http://site.icu-project.org/ ICU項目]庫。如果您需要使用Unicode,請將其[//www.mediawiki.org/wiki/Unicode_normalization_considerations 升級]。",
'config-no-db' => '找不到合適的數據庫驅動!您需要為PHP安裝數據庫驅動。目前支持以下數據庫:$1。
請考慮將數據庫統一放置在某處,如<code>/var/lib/mediawiki/yourwiki</code>下。",
'config-oracle-def-ts' => '默認表空間:',
'config-oracle-temp-ts' => '臨時表空間:',
- 'config-type-ibm_db2' => 'IBM DB2',
'config-support-info' => 'MediaWiki支持以下數據庫系統:
$1
'config-support-postgres' => '* $1是一種流行的開源數據庫系統,可作為MySQL的替代([http://www.php.net/manual/en/pgsql.installation.php 如何將對PostgreSQL的支持編譯進PHP中])。本程序中可能依然存在一些小而明顯的錯誤,因此並不建議在生產環境中使用該數據庫系統。',
'config-support-sqlite' => '* $1是一種輕量級的數據庫系統,能被良好地支持。([http://www.php.net/manual/en/pdo.installation.php 如何將對SQLite的支持編譯進PHP中],須使用PDO)',
'config-support-oracle' => '* $1是一種商用企業級的數據庫。([http://www.php.net/manual/en/oci8.installation.php 如何將對OCI8的支持編譯進PHP中])',
- 'config-support-ibm_db2' => '* $1是一種商用企業級數據庫。', # Fuzzy
'config-header-mysql' => 'MySQL 的設定',
'config-header-postgres' => 'PostgreSQL設置',
'config-header-sqlite' => 'SQLite 的設定',
'config-header-oracle' => '甲骨文設定',
- 'config-header-ibm_db2' => 'IBM DB2設置',
'config-invalid-db-type' => '無效的資料庫類型',
'config-missing-db-name' => '您必須為“數據庫名稱”輸入內容',
'config-missing-db-host' => '您必須為“數據庫主機”輸入內容',
'config-mysql-charset-help' => "在'''二進制模式'''下,MediaWiki會將UTF-8編碼的文本存於數據庫的二進制字段中。相對於MySQL的UTF-8模式,這種方法效率更高,並允許您使用全範圍的Unicode字符。
在'''UTF-8模式'''下,MySQL將知道您數據使用的字符集,並能適當地提供和轉換內容。但這樣做您將無法在數據庫中存儲[//zh.wikipedia.org/wiki/基本多文種平面 基本多文種平面]以外的字符。",
- 'config-ibm_db2-low-db-pagesize' => "您的DB2數據庫默認表空間的頁長(pagesize)不足。至少需要'''32K'''或更大的頁長。",
'config-site-name' => 'Wiki的名稱:',
'config-site-name-help' => '填入的內容會出現在瀏覽器的標題欄以及其他多處位置中。',
'config-site-name-blank' => '輸入站點名稱。',
}
}
-
/**
* Check the libicu version
*/
## Uncomment this to disable output compression
# \$wgDisableOutputCompression = true;
-\$wgSitename = \"{$this->values['wgSitename']}\";
+\$wgSitename = \"{$this->values['wgSitename']}\";
{$metaNamespace}
## The URL base path to the directory containing the wiki;
## defaults for all runtime URL paths are based off of this.
## For more information on customizing the URLs
## (like /w/index.php/Page_title to /wiki/Page_title) please see:
## http://www.mediawiki.org/wiki/Manual:Short_URL
-\$wgScriptPath = \"{$this->values['wgScriptPath']}\";
-\$wgScriptExtension = \"{$this->values['wgScriptExtension']}\";
+\$wgScriptPath = \"{$this->values['wgScriptPath']}\";
+\$wgScriptExtension = \"{$this->values['wgScriptExtension']}\";
## The protocol and server name to use in fully-qualified URLs
-\$wgServer = \"{$this->values['wgServer']}\";
+\$wgServer = \"{$this->values['wgServer']}\";
## The relative URL path to the skins directory
-\$wgStylePath = \"\$wgScriptPath/skins\";
+\$wgStylePath = \"\$wgScriptPath/skins\";
## The relative URL path to the logo. Make sure you change this from the default,
## or else you'll overwrite your logo when you upgrade!
-\$wgLogo = \"\$wgStylePath/common/images/wiki.png\";
+\$wgLogo = \"\$wgStylePath/common/images/wiki.png\";
## UPO means: this is also a user preference option
-\$wgEnableEmail = {$this->values['wgEnableEmail']};
-\$wgEnableUserEmail = {$this->values['wgEnableUserEmail']}; # UPO
+\$wgEnableEmail = {$this->values['wgEnableEmail']};
+\$wgEnableUserEmail = {$this->values['wgEnableUserEmail']}; # UPO
\$wgEmergencyContact = \"{$this->values['wgEmergencyContact']}\";
-\$wgPasswordSender = \"{$this->values['wgPasswordSender']}\";
+\$wgPasswordSender = \"{$this->values['wgPasswordSender']}\";
-\$wgEnotifUserTalk = {$this->values['wgEnotifUserTalk']}; # UPO
-\$wgEnotifWatchlist = {$this->values['wgEnotifWatchlist']}; # UPO
+\$wgEnotifUserTalk = {$this->values['wgEnotifUserTalk']}; # UPO
+\$wgEnotifWatchlist = {$this->values['wgEnotifWatchlist']}; # UPO
\$wgEmailAuthentication = {$this->values['wgEmailAuthentication']};
## Database settings
-\$wgDBtype = \"{$this->values['wgDBtype']}\";
-\$wgDBserver = \"{$this->values['wgDBserver']}\";
-\$wgDBname = \"{$this->values['wgDBname']}\";
-\$wgDBuser = \"{$this->values['wgDBuser']}\";
-\$wgDBpassword = \"{$this->values['wgDBpassword']}\";
+\$wgDBtype = \"{$this->values['wgDBtype']}\";
+\$wgDBserver = \"{$this->values['wgDBserver']}\";
+\$wgDBname = \"{$this->values['wgDBname']}\";
+\$wgDBuser = \"{$this->values['wgDBuser']}\";
+\$wgDBpassword = \"{$this->values['wgDBpassword']}\";
{$this->dbSettings}
## Shared memory settings
-\$wgMainCacheType = $cacheType;
+\$wgMainCacheType = $cacheType;
\$wgMemCachedServers = $mcservers;
## To enable image uploads, make sure the 'images' directory
## is writable, then set this to true:
-\$wgEnableUploads = {$this->values['wgEnableUploads']};
+\$wgEnableUploads = {$this->values['wgEnableUploads']};
{$magic}\$wgUseImageMagick = true;
{$magic}\$wgImageMagickConvertCommand = \"{$this->values['wgImageMagickConvertCommand']}\";
# InstantCommons allows wiki to use images from http://commons.wikimedia.org
-\$wgUseInstantCommons = {$this->values['wgUseInstantCommons']};
+\$wgUseInstantCommons = {$this->values['wgUseInstantCommons']};
## If you use ImageMagick (or any other shell command) on a
## Linux server, this will need to be set to the name of an
## appropriate copyright notice / icon. GNU Free Documentation
## License and Creative Commons licenses are supported so far.
\$wgRightsPage = \"\"; # Set to the title of a wiki page that describes your license/copyright
-\$wgRightsUrl = \"{$this->values['wgRightsUrl']}\";
+\$wgRightsUrl = \"{$this->values['wgRightsUrl']}\";
\$wgRightsText = \"{$this->values['wgRightsText']}\";
\$wgRightsIcon = \"{$this->values['wgRightsIcon']}\";
$tblOpts = LocalSettingsGenerator::escapePhpString( $this->getTableOptions() );
return
"# MySQL specific settings
-\$wgDBprefix = \"{$prefix}\";
+\$wgDBprefix = \"{$prefix}\";
# MySQL table options to use during installation or update
-\$wgDBTableOptions = \"{$tblOpts}\";
+\$wgDBTableOptions = \"{$tblOpts}\";
# Experimental charset support for MySQL 5.0.
\$wgDBmysql5 = {$dbmysql5};";
if ( $prev_title == $row->cur_title && $prev_namespace == $row->cur_namespace ) {
$deleteId[] = $row->cur_id;
}
- $prev_title = $row->cur_title;
+ $prev_title = $row->cur_title;
$prev_namespace = $row->cur_namespace;
}
$sql = "DELETE FROM $cur WHERE cur_id IN ( " . join( ',', $deleteId ) . ')';
$this->parent->addInstallStep( $callback, 'database' );
}
-
public function setupDatabase() {
$status = Status::newGood();
return $status;
$prefix = $this->getVar( 'wgDBprefix' );
return
"# Oracle specific settings
-\$wgDBprefix = \"{$prefix}\";
+\$wgDBprefix = \"{$prefix}\";
";
}
$schema = $this->getVar( 'wgDBmwschema' );
return
"# Postgres specific settings
-\$wgDBport = \"{$port}\";
-\$wgDBmwschema = \"{$schema}\";";
+\$wgDBport = \"{$port}\";
+\$wgDBmwschema = \"{$schema}\";";
}
public function preUpgrade() {
$module = DatabaseSqlite::getFulltextSearchModule();
$fts3tTable = $this->db->checkForEnabledSearch();
- if ( $fts3tTable && !$module ) {
+ if ( $fts3tTable && !$module ) {
$status->warning( 'config-sqlite-fts3-downgrade' );
$this->db->sourceFile( "$IP/maintenance/sqlite/archives/searchindex-no-fts.sql" );
} elseif ( !$fts3tTable && $module == 'FTS3' ) {
$dir = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgSQLiteDataDir' ) );
return
"# SQLite-specific settings
-\$wgSQLiteDataDir = \"{$dir}\";";
+\$wgSQLiteDataDir = \"{$dir}\";";
}
}
protected function sqliteSetupSearchindex() {
$module = DatabaseSqlite::getFulltextSearchModule();
$fts3tTable = $this->updateRowExists( 'fts3' );
- if ( $fts3tTable && !$module ) {
+ if ( $fts3tTable && !$module ) {
$this->applyPatch( 'searchindex-no-fts.sql', false, 'PHP is missing FTS3 support, downgrading tables' );
} elseif ( !$fts3tTable && $module == 'FTS3' ) {
$this->applyPatch( 'searchindex-fts3.sql', false, "Adding FTS3 search capabilities" );
* @param $params array
*/
protected function __construct( array $params ) {
- $this->wiki = $params['wiki'];
- $this->type = $params['type'];
- $this->order = isset( $params['order'] ) ? $params['order'] : 'random';
+ $this->wiki = $params['wiki'];
+ $this->type = $params['type'];
+ $this->order = isset( $params['order'] ) ? $params['order'] : 'random';
$this->claimTTL = isset( $params['claimTTL'] ) ? $params['claimTTL'] : 0;
$this->maxTries = isset( $params['maxTries'] ) ? $params['maxTries'] : 3;
}
* @since 1.21
*/
class JobQueueDB extends JobQueue {
- const ROOTJOB_TTL = 1209600; // integer; seconds to remember root jobs (14 days)
+ const ROOTJOB_TTL = 1209600; // integer; seconds to remember root jobs (14 days)
const CACHE_TTL_SHORT = 30; // integer; seconds to cache info without re-validating
- const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
- const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed
- const MAX_JOB_RANDOM = 2147483647; // integer; 2^31 - 1, used for job_random
- const MAX_OFFSET = 255; // integer; maximum number of rows to skip
+ const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
+ const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed
+ const MAX_JOB_RANDOM = 2147483647; // integer; 2^31 - 1, used for job_random
+ const MAX_OFFSET = 255; // integer; maximum number of rows to skip
protected $cluster = false; // string; name of an external DB cluster
$row = $this->claimOldest( $uuid );
} else { // random first
$rand = mt_rand( 0, self::MAX_JOB_RANDOM ); // encourage concurrent UPDATEs
- $gte = (bool)mt_rand( 0, 1 ); // find rows with rand before/after $rand
- $row = $this->claimRandom( $uuid, $rand, $gte );
+ $gte = (bool)mt_rand( 0, 1 ); // find rows with rand before/after $rand
+ $row = $this->claimRandom( $uuid, $rand, $gte );
}
// Check if we found a row to reserve...
if ( !$row ) {
// For small queues, using OFFSET will overshoot and return no rows more often.
// Instead, this uses job_random to pick a row (possibly checking both directions).
$ineq = $gte ? '>=' : '<=';
- $dir = $gte ? 'ASC' : 'DESC';
- $row = $dbw->selectRow( 'job', '*', // find a random job
+ $dir = $gte ? 'ASC' : 'DESC';
+ $row = $dbw->selectRow( 'job', '*', // find a random job
array(
'job_cmd' => $this->type,
'job_token' => '', // unclaimed
protected $wiki; // string; wiki ID
const TYPE_DEFAULT = 1; // integer; jobs popped by default
- const TYPE_ANY = 2; // integer; any job
+ const TYPE_ANY = 2; // integer; any job
const USE_CACHE = 1; // integer; use process or persistent cache
protected $server; // string; server address
- const ROOTJOB_TTL = 1209600; // integer; seconds to remember root jobs (14 days)
+ const ROOTJOB_TTL = 1209600; // integer; seconds to remember root jobs (14 days)
const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed (7 days)
protected $key; // string; key to prefix the queue keys with (used for testing)
*/
public static function newFromJob( Job $job ) {
$djob = new self( $job->getTitle(), $job->getParams(), $job->getId() );
- $djob->command = $job->getType();
- $djob->params = is_array( $djob->params ) ? $djob->params : array();
- $djob->params = array( 'isDuplicate' => true ) + $djob->params;
+ $djob->command = $job->getType();
+ $djob->params = is_array( $djob->params ) ? $djob->params : array();
+ $djob->params = array( 'isDuplicate' => true ) + $djob->params;
$djob->metadata = $job->metadata;
return $djob;
}
parent::__construct( 'htmlCacheUpdate', $title, $params, $id );
- $this->rowsPerJob = $wgUpdateRowsPerJob;
+ $this->rowsPerJob = $wgUpdateRowsPerJob;
$this->rowsPerQuery = $wgUpdateRowsPerQuery;
- $this->blCache = $title->getBacklinkCache();
+ $this->blCache = $title->getBacklinkCache();
}
public function run() {
$masterPos = false;
}
- $tbc = $this->title->getBacklinkCache();
+ $tbc = $this->title->getBacklinkCache();
$jobs = array(); // jobs to insert
if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
*/
protected function getSingleTitleJobs( $table, $masterPos ) {
# The "start"/"end" fields are not set for the base jobs
- $start = isset( $this->params['start'] ) ? $this->params['start'] : false;
- $end = isset( $this->params['end'] ) ? $this->params['end'] : false;
+ $start = isset( $this->params['start'] ) ? $this->params['start'] : false;
+ $end = isset( $this->params['end'] ) ? $this->params['end'] : false;
$titles = $this->title->getBacklinkCache()->getLinks( $table, $start, $end );
# Convert into single page refresh links jobs.
# This handles well when in sapi mode and is useful in any case for job
'cursor_west' => null,
'four_notation_quantity' => null,
'four_notation_color' => null,
- 'box_shadow' => null,
- 'text_shadow1' => null,
- 'text_shadow2' => null,
'bg_horizontal_percentage' => null,
'bg_horizontal_percentage_x' => null,
);
$patterns['ident'] = "-?{$patterns['nmstart']}{$patterns['nmchar']}*";
$patterns['quantity'] = "{$patterns['num']}(?:\s*{$patterns['unit']}|{$patterns['ident']})?";
$patterns['possibly_negative_quantity'] = "((?:-?{$patterns['quantity']})|(?:inherit|auto))";
- $patterns['color'] = "(#?{$patterns['nmchar']}+|(?:rgba?|hsla?)\([ \d.,%-]+\))";
+ $patterns['color'] = "(#?{$patterns['nmchar']}+)";
$patterns['url_chars'] = "(?:{$patterns['url_special_chars']}|{$patterns['nonAscii']}|{$patterns['escape']})*";
$patterns['lookahead_not_open_brace'] = "(?!({$patterns['nmchar']}|\r?\n|\s|#|\:|\.|\,|\+|>)*?{)";
$patterns['lookahead_not_closing_paren'] = "(?!{$patterns['url_chars']}?{$patterns['valid_after_uri_chars']}\))";
$patterns['rtl_in_url'] = "/{$patterns['lookbehind_not_letter']}(rtl){$patterns['lookahead_for_closing_paren']}/i";
$patterns['cursor_east'] = "/{$patterns['lookbehind_not_letter']}([ns]?)e-resize/";
$patterns['cursor_west'] = "/{$patterns['lookbehind_not_letter']}([ns]?)w-resize/";
- $patterns['four_notation_quantity'] = "/(:\s*){$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}(\s*[;}])/i";
- $patterns['four_notation_color'] = "/(-color\s*:\s*){$patterns['color']}(\s+){$patterns['color']}(\s+){$patterns['color']}(\s+){$patterns['color']}(\s*[;}])/i";
- $patterns['box_shadow'] = "/(box-shadow\s*:\s*(?:inset\s*)?){$patterns['possibly_negative_quantity']}/i";
- $patterns['text_shadow1'] = "/(text-shadow\s*:\s*){$patterns['color']}(\s*){$patterns['possibly_negative_quantity']}/i";
- $patterns['text_shadow2'] = "/(text-shadow\s*:\s*){$patterns['possibly_negative_quantity']}/i";
+ $patterns['four_notation_quantity'] = "/{$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}/i";
+ $patterns['four_notation_color'] = "/(-color\s*:\s*){$patterns['color']}(\s+){$patterns['color']}(\s+){$patterns['color']}(\s+){$patterns['color']}/i";
// The two regexes below are parenthesized differently then in the original implementation to make the
// callback's job more straightforward
$patterns['bg_horizontal_percentage'] = "/(background(?:-position)?\s*:\s*[^%]*?)(-?{$patterns['num']})(%\s*(?:{$patterns['quantity']}|{$patterns['ident']}))/";
$css = self::fixCursorProperties( $css );
$css = self::fixFourPartNotation( $css );
$css = self::fixBackgroundPosition( $css );
- $css = self::fixShadows( $css );
// Detokenize stuff we tokenized before
$css = $comments->detokenize( $css );
* @return string
*/
private static function fixFourPartNotation( $css ) {
- $css = preg_replace( self::$patterns['four_notation_quantity'], '$1$2$3$8$5$6$7$4$9', $css );
- $css = preg_replace( self::$patterns['four_notation_color'], '$1$2$3$8$5$6$7$4$9', $css );
-
- return $css;
- }
-
- /**
- * Negates horizontal offset in box-shadow and text-shadow rules.
- *
- * @param $css string
- * @return string
- */
- private static function fixShadows( $css ) {
- // Flips the sign of a CSS value, possibly with a unit.
- // (We can't just negate the value with unary minus due to the units.)
- $flipSign = function ( $cssValue ) {
- // Don't mangle zeroes
- if ( intval( $cssValue ) === 0 ) {
- return $cssValue;
- } elseif ( $cssValue[0] === '-' ) {
- return substr( $cssValue, 1 );
- } else {
- return "-" . $cssValue;
- }
- };
-
- $css = preg_replace_callback( self::$patterns['box_shadow'], function ( $matches ) use ( $flipSign ) {
- return $matches[1] . $flipSign( $matches[2] );
- }, $css );
-
- $css = preg_replace_callback( self::$patterns['text_shadow1'], function ( $matches ) use ( $flipSign ) {
- return $matches[1] . $matches[2] . $matches[3] . $flipSign( $matches[4] );
- }, $css );
-
- $css = preg_replace_callback( self::$patterns['text_shadow2'], function ( $matches ) use ( $flipSign ) {
- return $matches[1] . $flipSign( $matches[2] );
- }, $css );
+ $css = preg_replace( self::$patterns['four_notation_quantity'], '$1$2$7$4$5$6$3', $css );
+ $css = preg_replace( self::$patterns['four_notation_color'], '$1$2$3$8$5$6$7$4', $css );
return $css;
}
/**
* Returns an array holding all the data that should go into serialization calls.
* This is intended to allow overloading without having to reimplement the
- * behaviour of this base class.
+ * behavior of this base class.
*
* @since 1.20
*
* whether the script filename has been obscured.
*
* The function returns false if the server is not known to have this
- * behaviour. Microsoft IIS in particular is known to decode escaped script
+ * behavior. Microsoft IIS in particular is known to decode escaped script
* filenames.
*
* SERVER_SOFTWARE typically contains either a plain string such as "Zeus",
}
$changeText = $this->context->getLanguage()->listToText( $changes );
-
$newParams = array_slice( $params, 0, 3 );
$newParams[3] = $changeText;
$count = count( explode( ',', $params[$paramStart] ) );
return $messages[$flag];
}
-
/**
* Name of the log.
* @return Message
return true;
}
-
/**
* Extracts the width/height if the image will be scaled before rotating
*
return array( $width, $height );
}
-
/**
* Function that returns the number of pixels to be thumbnailed.
* Intended for animated GIFs to multiply by the number of frames.
return $this->getClientScalingThumbnailImage( $image, $scalerParams );
}
-
if ( $scaler == 'client' ) {
# Client-side image scaling, use the source URL
# Using the destination URL in a TRANSFORM_LATER request would be incorrect
$rotation = $this->getRotation( $image );
list( $width, $height ) = $this->extractPreRotationDimensions( $params, $rotation );
- $cmd =
+ $cmd =
wfEscapeShellArg( $wgImageMagickConvertCommand ) .
// Specify white background color, will be used for transparent images
// in Internet Explorer/Windows instead of default black.
# Escape glob chars
$path = preg_replace( '/[*?\[\]{}]/', '\\\\\0', $path );
- return $this->escapeMagickPath( $path, $scene );
+ return self::escapeMagickPath( $path, $scene );
}
/**
*/
function escapeMagickOutput( $path, $scene = false ) {
$path = str_replace( '%', '%%', $path );
- return $this->escapeMagickPath( $path, $scene );
+ return self::escapeMagickPath( $path, $scene );
}
/**
}
}
+ /**
+ * @param $file File
+ * @param $params array Rotate parameters.
+ * 'rotation' clockwise rotation in degrees, allowed are multiples of 90
+ * @since 1.21
+ * @return bool
+ */
+ public static function rotate( $file, $params ) {
+ global $wgImageMagickConvertCommand;
+
+ $rotation = ( $params[ 'rotation' ] + self::getRotation( $file ) ) % 360;
+ $scene = false;
+
+ $scaler = self::getScalerType( null, false );
+ switch ( $scaler ) {
+ case 'im':
+ $cmd = wfEscapeShellArg( $wgImageMagickConvertCommand ) . " " .
+ wfEscapeShellArg( self::escapeMagickInput( $params[ 'srcPath' ], $scene ) ) .
+ " -rotate -$rotation " .
+ wfEscapeShellArg( self::escapeMagickOutput( $params[ 'dstPath' ] ) ) . " 2>&1";
+ wfDebug( __METHOD__ . ": running ImageMagick: $cmd\n" );
+ wfProfileIn( 'convert' );
+ $retval = 0;
+ $err = wfShellExec( $cmd, $retval, $env );
+ wfProfileOut( 'convert' );
+ if ( $retval !== 0 ) {
+ self::logErrorForExternalProcess( $retval, $err, $cmd );
+ return new MediaTransformError( 'thumbnail_error', 0, 0, $err );
+ }
+ return false;
+ case 'imext':
+ $im = new Imagick();
+ $im->readImage( $params['srcPath'] );
+ if ( !$im->rotateImage( new ImagickPixel( 'white' ), 360 - $rotation ) ) {
+ return new MediaTransformError( 'thumbnail_error', 0, 0,
+ "Error rotating $rotation degrees" );
+ }
+ $result = $im->writeImage( $params['dstPath'] );
+ if ( !$result ) {
+ return new MediaTransformError( 'thumbnail_error', 0, 0,
+ "Unable to write image to {$params['dstPath']}" );
+ }
+ return false;
+ default:
+ return new MediaTransformError( 'thumbnail_error', 0, 0,
+ "$scaler rotation not implemented" );
+ }
+ }
+
/**
* Rerurns whether the file needs to be rendered. Returns true if the
* file requires rotation and we are able to rotate it.
private $iptcType = 'iptc-no-hash';
/**
- * This does the photoshop image resource app13 block
- * of interest, IPTC-IIM metadata is stored here.
- *
- * Mostly just calls doPSIR and doIPTC
- *
- * @param String $app13 String containing app13 block from jpeg file
- */
+ * This does the photoshop image resource app13 block
+ * of interest, IPTC-IIM metadata is stored here.
+ *
+ * Mostly just calls doPSIR and doIPTC
+ *
+ * @param String $app13 String containing app13 block from jpeg file
+ */
private function doApp13 ( $app13 ) {
try {
$this->iptcType = JpegMetadataExtractor::doPSIR( $app13 );
$this->addMetadata( $iptc, $this->iptcType );
}
-
/**
* Get exif info using exif class.
* Basically what used to be in BitmapHandler::getMetadata().
}
}
/** Add misc metadata. Warning: atm if the metadata category
- * doesn't have a priority, it will be silently discarded.
- *
- * @param Array $metaArray array of metadata values
- * @param string $type type. defaults to other. if two things have the same type they're merged
- */
+ * doesn't have a priority, it will be silently discarded.
+ *
+ * @param Array $metaArray array of metadata values
+ * @param string $type type. defaults to other. if two things have the same type they're merged
+ */
function addMetadata ( $metaArray, $type = 'other' ) {
if ( isset( $this->metadata[$type] ) ) {
/* merge with old data */
}
/**
- * Merge together the various types of metadata
- * the different types have different priorites,
- * and are merged in order.
- *
- * This function is generally called by the media handlers' getMetadata()
- *
- * @return Array metadata array
- */
+ * Merge together the various types of metadata
+ * the different types have different priorites,
+ * and are merged in order.
+ *
+ * This function is generally called by the media handlers' getMetadata()
+ *
+ * @return Array metadata array
+ */
function getMetadataArray () {
// this seems a bit ugly... This is all so its merged in right order
// based on the MWG recomendation.
}
}
-
-
}
return $info !== false;
}
-
/**
* Return data in the style of getimagesize()
* @return array or false on failure
$data = $this->getInfo();
if( $data !== false ) {
- $width = $data['width'];
+ $width = $data['width'];
$height = $data['height'];
return array( $width, $height, 'DjVu',
*/
class Exif {
- const BYTE = 1; //!< An 8-bit (1-byte) unsigned integer.
- const ASCII = 2; //!< An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.
- const SHORT = 3; //!< A 16-bit (2-byte) unsigned integer.
- const LONG = 4; //!< A 32-bit (4-byte) unsigned integer.
- const RATIONAL = 5; //!< Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator
- const UNDEFINED = 7; //!< An 8-bit byte that can take any value depending on the field definition
- const SLONG = 9; //!< A 32-bit (4-byte) signed integer (2's complement notation),
- const SRATIONAL = 10; //!< Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
- const IGNORE = -1; // A fake value for things we don't want or don't support.
+ const BYTE = 1; //!< An 8-bit (1-byte) unsigned integer.
+ const ASCII = 2; //!< An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.
+ const SHORT = 3; //!< A 16-bit (2-byte) unsigned integer.
+ const LONG = 4; //!< A 32-bit (4-byte) unsigned integer.
+ const RATIONAL = 5; //!< Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator
+ const UNDEFINED = 7; //!< An 8-bit byte that can take any value depending on the field definition
+ const SLONG = 9; //!< A 32-bit (4-byte) signed integer (2's complement notation),
+ const SRATIONAL = 10; //!< Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
+ const IGNORE = -1; // A fake value for things we don't want or don't support.
//@{
/* @var array
}
/**
- * Collapse some fields together.
- * This converts some fields from exif form, to a more friendly form.
- * For example GPS latitude to a single number.
- *
- * The rationale behind this is that we're storing data, not presenting to the user
- * For example a longitude is a single number describing how far away you are from
- * the prime meridian. Well it might be nice to split it up into minutes and seconds
- * for the user, it doesn't really make sense to split a single number into 4 parts
- * for storage. (degrees, minutes, second, direction vs single floating point number).
- *
- * Other things this might do (not really sure if they make sense or not):
- * Dates -> mediawiki date format.
- * convert values that can be in different units to be in one standardized unit.
- *
- * As an alternative approach, some of this could be done in the validate phase
- * if we make up our own types like Exif::DATE.
- */
+ * Collapse some fields together.
+ * This converts some fields from exif form, to a more friendly form.
+ * For example GPS latitude to a single number.
+ *
+ * The rationale behind this is that we're storing data, not presenting to the user
+ * For example a longitude is a single number describing how far away you are from
+ * the prime meridian. Well it might be nice to split it up into minutes and seconds
+ * for the user, it doesn't really make sense to split a single number into 4 parts
+ * for storage. (degrees, minutes, second, direction vs single floating point number).
+ *
+ * Other things this might do (not really sure if they make sense or not):
+ * Dates -> mediawiki date format.
+ * convert values that can be in different units to be in one standardized unit.
+ *
+ * As an alternative approach, some of this could be done in the validate phase
+ * if we make up our own types like Exif::DATE.
+ */
function collapseData( ) {
$this->exifGPStoNumber( 'GPSLatitude' );
}
/**
- * Do userComment tags and similar. See pg. 34 of exif standard.
- * basically first 8 bytes is charset, rest is value.
- * This has not been tested on any shift-JIS strings.
- * @param $prop String prop name.
- */
+ * Do userComment tags and similar. See pg. 34 of exif standard.
+ * basically first 8 bytes is charset, rest is value.
+ * This has not been tested on any shift-JIS strings.
+ * @param $prop String prop name.
+ */
private function charCodeString ( $prop ) {
if ( isset( $this->mFilteredExifData[$prop] ) ) {
}
}
/**
- * Convert an Exif::UNDEFINED from a raw binary string
- * to its value. This is sometimes needed depending on
- * the type of UNDEFINED field
- * @param $prop String name of property
- */
+ * Convert an Exif::UNDEFINED from a raw binary string
+ * to its value. This is sometimes needed depending on
+ * the type of UNDEFINED field
+ * @param $prop String name of property
+ */
private function exifPropToOrd ( $prop ) {
if ( isset( $this->mFilteredExifData[$prop] ) ) {
$this->mFilteredExifData[$prop] = ord( $this->mFilteredExifData[$prop] );
}
}
/**
- * Convert gps in exif form to a single floating point number
- * for example 10 degress 20`40`` S -> -10.34444
- * @param String $prop a gps coordinate exif tag name (like GPSLongitude)
- */
+ * Convert gps in exif form to a single floating point number
+ * for example 10 degress 20`40`` S -> -10.34444
+ * @param String $prop a gps coordinate exif tag name (like GPSLongitude)
+ */
private function exifGPStoNumber ( $prop ) {
$loc =& $this->mFilteredExifData[$prop];
$dir =& $this->mFilteredExifData[$prop . 'Ref'];
}
$data = $file->getMetadata();
- return $this->getRotationForExif( $data );
+ return self::getRotationForExif( $data );
}
/**
* @file
*/
-
/**
* Format Image metadata values into a human readable form.
*
}
break;
-
case 'GPSTrackRef':
case 'GPSImgDirectionRef':
case 'GPSDestBearingRef':
}
/**
- * A function to collapse multivalued tags into a single value.
- * This turns an array of (for example) authors into a bulleted list.
- *
- * This is public on the basis it might be useful outside of this class.
- *
- * @param $vals Array array of values
- * @param $type String Type of array (either lang, ul, ol).
- * lang = language assoc array with keys being the lang code
- * ul = unordered list, ol = ordered list
- * type can also come from the '_type' member of $vals.
- * @param $noHtml Boolean If to avoid returning anything resembling
- * html. (Ugly hack for backwards compatibility with old mediawiki).
- * @return String single value (in wiki-syntax).
- */
+ * A function to collapse multivalued tags into a single value.
+ * This turns an array of (for example) authors into a bulleted list.
+ *
+ * This is public on the basis it might be useful outside of this class.
+ *
+ * @param $vals Array array of values
+ * @param $type String Type of array (either lang, ul, ol).
+ * lang = language assoc array with keys being the lang code
+ * ul = unordered list, ol = ordered list
+ * type can also come from the '_type' member of $vals.
+ * @param $noHtml Boolean If to avoid returning anything resembling
+ * html. (Ugly hack for backwards compatibility with old mediawiki).
+ * @return String single value (in wiki-syntax).
+ */
public static function flattenArray( $vals, $type = 'ul', $noHtml = false ) {
if ( isset( $vals['_type'] ) ) {
$type = $vals['_type'];
*
* @deprecated since 1.18
*
-**/
+ */
class FormatExif {
var $meta;
*/
static function readGCT( $fh, $bpp ) {
if ( $bpp > 0 ) {
- for( $i=1; $i<=pow( 2, $bpp ); ++$i ) {
+ for( $i = 1; $i <= pow( 2, $bpp ); ++$i ) {
fread( $fh, 3 );
}
}
class IPTC {
/**
- * This takes the results of iptcparse() and puts it into a
- * form that can be handled by mediawiki. Generally called from
- * BitmapMetadataHandler::doApp13.
- *
- * @see http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
- *
- * @param $rawData String app13 block from jpeg containing iptc/iim data
- * @return Array iptc metadata array
- */
+ * This takes the results of iptcparse() and puts it into a
+ * form that can be handled by mediawiki. Generally called from
+ * BitmapMetadataHandler::doApp13.
+ *
+ * @see http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
+ *
+ * @param $rawData String app13 block from jpeg containing iptc/iim data
+ * @return Array iptc metadata array
+ */
static function parse( $rawData ) {
$parsed = iptcparse( $rawData );
$data = Array();
/* original transmission ref.
* "A code representing the location of original transmission ac-
* cording to practises of the provider."
- */
+ */
$data['OriginalTransmissionRef'] = self::convIPTC( $val, $c );
break;
case '2#118': /*contact*/
}
/**
- * Convert an iptc date and time tags into the exif format
- *
- * @todo Potentially this should also capture the timezone offset.
- * @param Array $date The date tag
- * @param Array $time The time tag
- * @param $c
- * @return String Date in exif format.
- */
+ * Convert an iptc date and time tags into the exif format
+ *
+ * @todo Potentially this should also capture the timezone offset.
+ * @param Array $date The date tag
+ * @param Array $time The time tag
+ * @param $c
+ * @return String Date in exif format.
+ */
private static function timeHelper( $date, $time, $c ) {
if ( count( $date ) === 1 ) {
//the standard says this should always be 1
}
/**
- * Helper function to convert charset for iptc values.
- * @param $data string|array The iptc string
- * @param $charset String: The charset
+ * Helper function to convert charset for iptc values.
+ * @param $data string|array The iptc string
+ * @param $charset String: The charset
*
* @return string|array
- */
+ */
private static function convIPTC ( $data, $charset ) {
if ( is_array( $data ) ) {
foreach ( $data as &$val ) {
return $data;
}
/**
- * Helper function of a helper function to convert charset for iptc values.
- * @param $data Mixed String or Array: The iptc string
- * @param $charset String: The charset
- *
- * @return string
- */
+ * Helper function of a helper function to convert charset for iptc values.
+ * @param $data Mixed String or Array: The iptc string
+ * @param $charset String: The charset
+ *
+ * @return string
+ */
private static function convIPTCHelper ( $data, $charset ) {
if ( $charset ) {
wfSuppressWarnings();
}
/**
- * take the value of 1:90 tag and returns a charset
- * @param String $tag 1:90 tag.
- * @return string charset name or "?"
- * Warning, this function does not (and is not intended to) detect
- * all iso 2022 escape codes. In practise, the code for utf-8 is the
- * only code that seems to have wide use. It does detect that code.
- */
+ * take the value of 1:90 tag and returns a charset
+ * @param String $tag 1:90 tag.
+ * @return string charset name or "?"
+ * Warning, this function does not (and is not intended to) detect
+ * all iso 2022 escape codes. In practise, the code for utf-8 is the
+ * only code that seems to have wide use. It does detect that code.
+ */
static function getCharset( $tag ) {
//According to iim standard, charset is defined by the tag 1:90.
case "\x1b(K":
$c = "ISO646-DE";
break;
- case "\x1b(N": //crylic
+ case "\x1b(N": //crylic
$c = "ISO_5427";
break;
case "\x1b(`": //iso646-NO
$params['height'] = $params['physicalHeight'];
}
-
if ( !$this->validateThumbParams( $params['physicalWidth'],
$params['physicalHeight'], $srcWidth, $srcHeight, $mimeType ) ) {
return false;
}
}
+ /**
+ * @param $file File
+ * @param $params array Rotate parameters.
+ * 'rotation' clockwise rotation in degrees, allowed are multiples of 90
+ * @since 1.21
+ * @return bool
+ */
+ public static function rotate( $file, $params ) {
+ global $wgJpegTran;
+
+ $rotation = ( $params[ 'rotation' ] + self::getRotation( $file ) ) % 360;
+
+ if( $wgJpegTran && is_file( $wgJpegTran ) ){
+ $cmd = wfEscapeShellArg( $wgJpegTran ) .
+ " -rotate " . wfEscapeShellArg( $rotation ) .
+ " -outfile " . wfEscapeShellArg( $params[ 'dstPath' ] ) .
+ " " . wfEscapeShellArg( $params[ 'srcPath' ] ) . " 2>&1";
+ wfDebug( __METHOD__ . ": running jpgtran: $cmd\n" );
+ wfProfileIn( 'jpegtran' );
+ $retval = 0;
+ $err = wfShellExec( $cmd, $retval, $env );
+ wfProfileOut( 'jpegtran' );
+ if ( $retval !== 0 ) {
+ self::logErrorForExternalProcess( $retval, $err, $cmd );
+ return new MediaTransformError( 'thumbnail_error', 0, 0, $err );
+ }
+ return false;
+ } else {
+ return Bitmap::rotate( $file, $params );
+ }
+ }
+
}
// that many segments. Your average file has about 10.
/** Function to extract metadata segments of interest from jpeg files
- * based on GIFMetadataExtractor.
- *
- * we can almost use getimagesize to do this
- * but gis doesn't support having multiple app1 segments
- * and those can't extract xmp on files containing both exif and xmp data
- *
- * @param String $filename name of jpeg file
- * @return Array of interesting segments.
- * @throws MWException if given invalid file.
- */
+ * based on GIFMetadataExtractor.
+ *
+ * we can almost use getimagesize to do this
+ * but gis doesn't support having multiple app1 segments
+ * and those can't extract xmp on files containing both exif and xmp data
+ *
+ * @param String $filename name of jpeg file
+ * @return Array of interesting segments.
+ * @throws MWException if given invalid file.
+ */
static function segmentSplitter ( $filename ) {
$showXMP = function_exists( 'xml_parser_create_ns' );
}
/**
- * This reads the photoshop image resource.
- * Currently it only compares the iptc/iim hash
- * with the stored hash, which is used to determine the precedence
- * of the iptc data. In future it may extract some other info, like
- * url of copyright license.
- *
- * This should generally be called by BitmapMetadataHandler::doApp13()
- *
- * @param String $app13 photoshop psir app13 block from jpg.
- * @throws MWException (It gets caught next level up though)
- * @return String if the iptc hash is good or not.
- */
+ * This reads the photoshop image resource.
+ * Currently it only compares the iptc/iim hash
+ * with the stored hash, which is used to determine the precedence
+ * of the iptc data. In future it may extract some other info, like
+ * url of copyright license.
+ *
+ * This should generally be called by BitmapMetadataHandler::doApp13()
+ *
+ * @param String $app13 photoshop psir app13 block from jpg.
+ * @throws MWException (It gets caught next level up though)
+ * @return String if the iptc hash is good or not.
+ */
public static function doPSIR ( $app13 ) {
if ( !$app13 ) {
throw new MWException( "No App13 segment given" );
function getMetadata( $image, $path ) { return ''; }
/**
- * Get metadata version.
- *
- * This is not used for validating metadata, this is used for the api when returning
- * metadata, since api content formats should stay the same over time, and so things
- * using ForiegnApiRepo can keep backwards compatibility
- *
- * All core media handlers share a common version number, and extensions can
- * use the GetMetadataVersion hook to append to the array (they should append a unique
- * string so not to get confusing). If there was a media handler named 'foo' with metadata
- * version 3 it might add to the end of the array the element 'foo=3'. if the core metadata
- * version is 2, the end version string would look like '2;foo=3'.
- *
- * @return string version string
- */
+ * Get metadata version.
+ *
+ * This is not used for validating metadata, this is used for the api when returning
+ * metadata, since api content formats should stay the same over time, and so things
+ * using ForiegnApiRepo can keep backwards compatibility
+ *
+ * All core media handlers share a common version number, and extensions can
+ * use the GetMetadataVersion hook to append to the array (they should append a unique
+ * string so not to get confusing). If there was a media handler named 'foo' with metadata
+ * version 3 it might add to the end of the array the element 'foo=3'. if the core metadata
+ * version is 2, the end version string would look like '2;foo=3'.
+ *
+ * @return string version string
+ */
static function getMetadataVersion () {
$version = Array( '2' ); // core metadata version
wfRunHooks( 'GetMetadataVersion', Array( &$version ) );
}
/**
- * Convert metadata version.
- *
- * By default just returns $metadata, but can be used to allow
- * media handlers to convert between metadata versions.
- *
- * @param $metadata Mixed String or Array metadata array (serialized if string)
- * @param $version Integer target version
- * @return Array serialized metadata in specified version, or $metadata on fail.
- */
+ * Convert metadata version.
+ *
+ * By default just returns $metadata, but can be used to allow
+ * media handlers to convert between metadata versions.
+ *
+ * @param $metadata Mixed String or Array metadata array (serialized if string)
+ * @param $version Integer target version
+ * @return Array serialized metadata in specified version, or $metadata on fail.
+ */
function convertMetadataVersion( $metadata, $version = 1 ) {
if ( !is_array( $metadata ) ) {
return self::METADATA_GOOD;
}
-
/**
* Get a MediaTransformOutput object representing an alternate of the transformed
* output which will call an intermediary thumbnail assist script.
return $fields;
}
-
/**
* This is used to generate an array element for each metadata value
* That array is then used to generate the table of metadata values
public function filterThumbnailPurgeList( &$files, $options ) {
// Do nothing
}
+
+ /*
+ * True if the handler can rotate the media
+ * @since 1.21
+ * @return bool
+ */
+ public static function canRotate() {
+ return false;
+ }
}
*/
/**
-* Class for reading xmp data containing properties relevant to
-* images, and spitting out an array that FormatExif accepts.
-*
-* Note, this is not meant to recognize every possible thing you can
-* encode in XMP. It should recognize all the properties we want.
-* For example it doesn't have support for structures with multiple
-* nesting levels, as none of the properties we're supporting use that
-* feature. If it comes across properties it doesn't recognize, it should
-* ignore them.
-*
-* The public methods one would call in this class are
-* - parse( $content )
-* Reads in xmp content.
-* Can potentially be called multiple times with partial data each time.
-* - parseExtended( $content )
-* Reads XMPExtended blocks (jpeg files only).
-* - getResults
-* Outputs a results array.
-*
-* Note XMP kind of looks like rdf. They are not the same thing - XMP is
-* encoded as a specific subset of rdf. This class can read XMP. It cannot
-* read rdf.
-*
-*/
+ * Class for reading xmp data containing properties relevant to
+ * images, and spitting out an array that FormatExif accepts.
+ *
+ * Note, this is not meant to recognize every possible thing you can
+ * encode in XMP. It should recognize all the properties we want.
+ * For example it doesn't have support for structures with multiple
+ * nesting levels, as none of the properties we're supporting use that
+ * feature. If it comes across properties it doesn't recognize, it should
+ * ignore them.
+ *
+ * The public methods one would call in this class are
+ * - parse( $content )
+ * Reads in xmp content.
+ * Can potentially be called multiple times with partial data each time.
+ * - parseExtended( $content )
+ * Reads XMPExtended blocks (jpeg files only).
+ * - getResults
+ * Outputs a results array.
+ *
+ * Note XMP kind of looks like rdf. They are not the same thing - XMP is
+ * encoded as a specific subset of rdf. This class can read XMP. It cannot
+ * read rdf.
+ *
+ */
class XMPReader {
private $curItem = array(); // array to hold the current element (and previous element, and so on)
protected $items;
/**
- * These are various mode constants.
- * they are used to figure out what to do
- * with an element when its encountered.
- *
- * For example, MODE_IGNORE is used when processing
- * a property we're not interested in. So if a new
- * element pops up when we're in that mode, we ignore it.
- */
+ * These are various mode constants.
+ * they are used to figure out what to do
+ * with an element when its encountered.
+ *
+ * For example, MODE_IGNORE is used when processing
+ * a property we're not interested in. So if a new
+ * element pops up when we're in that mode, we ignore it.
+ */
const MODE_INITIAL = 0;
- const MODE_IGNORE = 1;
- const MODE_LI = 2;
+ const MODE_IGNORE = 1;
+ const MODE_LI = 2;
const MODE_LI_LANG = 3;
- const MODE_QDESC = 4;
+ const MODE_QDESC = 4;
// The following MODE constants are also used in the
// $items array to denote what type of property the item is.
- const MODE_SIMPLE = 10;
- const MODE_STRUCT = 11; // structure (associative array)
- const MODE_SEQ = 12; // ordered list
- const MODE_BAG = 13; // unordered list
- const MODE_LANG = 14;
- const MODE_ALT = 15; // non-language alt. Currently not implemented, and not needed atm.
+ const MODE_SIMPLE = 10;
+ const MODE_STRUCT = 11; // structure (associative array)
+ const MODE_SEQ = 12; // ordered list
+ const MODE_BAG = 13; // unordered list
+ const MODE_LANG = 14;
+ const MODE_ALT = 15; // non-language alt. Currently not implemented, and not needed atm.
const MODE_BAGSTRUCT = 16; // A BAG of Structs.
const NS_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
const NS_XML = 'http://www.w3.org/XML/1998/namespace';
-
/**
- * Constructor.
- *
- * Primary job is to initialize the XMLParser
- */
+ * Constructor.
+ *
+ * Primary job is to initialize the XMLParser
+ */
function __construct() {
if ( !function_exists( 'xml_parser_create_ns' ) ) {
}
/**
- * Main use is if a single item has multiple xmp documents describing it.
- * For example in jpeg's with extendedXMP
- */
+ * Main use is if a single item has multiple xmp documents describing it.
+ * For example in jpeg's with extendedXMP
+ */
private function resetXMLParser() {
if ( $this->xmlParser ) {
}
/** Destroy the xml parser
- *
- * Not sure if this is actually needed.
- */
+ *
+ * Not sure if this is actually needed.
+ */
function __destruct() {
// not sure if this is needed.
xml_parser_free( $this->xmlParser );
}
/** Get the result array. Do some post-processing before returning
- * the array, and transform any metadata that is special-cased.
- *
- * @return Array array of results as an array of arrays suitable for
- * FormatMetadata::getFormattedData().
- */
+ * the array, and transform any metadata that is special-cased.
+ *
+ * @return Array array of results as an array of arrays suitable for
+ * FormatMetadata::getFormattedData().
+ */
public function getResults() {
// xmp-special is for metadata that affects how stuff
// is extracted. For example xmpNote:HasExtendedXMP.
}
}
-
// We don't want to return the special values, since they're
// special and not info to be stored about the file.
unset( $data['xmp-special'] );
return false;
}
-
// we're not very robust here. we should accept it in the wrong order. To quote
// the xmp standard:
// "A JPEG writer should write the ExtendedXMP marker segments in order, immediately following the
}
/**
- * Character data handler
- * Called whenever character data is found in the xmp document.
- *
- * does nothing if we're in MODE_IGNORE or if the data is whitespace
- * throws an error if we're not in MODE_SIMPLE (as we're not allowed to have character
- * data in the other modes).
- *
- * As an example, this happens when we encounter XMP like:
- * <exif:DigitalZoomRatio>0/10</exif:DigitalZoomRatio>
- * and are processing the 0/10 bit.
- *
- * @param $parser XMLParser reference to the xml parser
- * @param $data String Character data
- * @throws MWException on invalid data
- */
+ * Character data handler
+ * Called whenever character data is found in the xmp document.
+ *
+ * does nothing if we're in MODE_IGNORE or if the data is whitespace
+ * throws an error if we're not in MODE_SIMPLE (as we're not allowed to have character
+ * data in the other modes).
+ *
+ * As an example, this happens when we encounter XMP like:
+ * <exif:DigitalZoomRatio>0/10</exif:DigitalZoomRatio>
+ * and are processing the 0/10 bit.
+ *
+ * @param $parser XMLParser reference to the xml parser
+ * @param $data String Character data
+ * @throws MWException on invalid data
+ */
function char( $parser, $data ) {
$data = trim( $data );
}
/** When we hit a closing element in MODE_IGNORE
- * Check to see if this is the element we started to ignore,
- * in which case we get out of MODE_IGNORE
- *
- * @param $elm String Namespace of element followed by a space and then tag name of element.
- */
+ * Check to see if this is the element we started to ignore,
+ * in which case we get out of MODE_IGNORE
+ *
+ * @param $elm String Namespace of element followed by a space and then tag name of element.
+ */
private function endElementModeIgnore ( $elm ) {
if ( $this->curItem[0] === $elm ) {
array_shift( $this->curItem );
}
/**
- * Hit a closing element when in MODE_SIMPLE.
- * This generally means that we finished processing a
- * property value, and now have to save the result to the
- * results array
- *
- * For example, when processing:
- * <exif:DigitalZoomRatio>0/10</exif:DigitalZoomRatio>
- * this deals with when we hit </exif:DigitalZoomRatio>.
- *
- * Or it could be if we hit the end element of a property
- * of a compound data structure (like a member of an array).
- *
- * @param $elm String namespace, space, and tag name.
- */
+ * Hit a closing element when in MODE_SIMPLE.
+ * This generally means that we finished processing a
+ * property value, and now have to save the result to the
+ * results array
+ *
+ * For example, when processing:
+ * <exif:DigitalZoomRatio>0/10</exif:DigitalZoomRatio>
+ * this deals with when we hit </exif:DigitalZoomRatio>.
+ *
+ * Or it could be if we hit the end element of a property
+ * of a compound data structure (like a member of an array).
+ *
+ * @param $elm String namespace, space, and tag name.
+ */
private function endElementModeSimple ( $elm ) {
if ( $this->charContent !== false ) {
if ( $this->processingArray ) {
}
/**
- * End element while in MODE_QDESC
- * mostly when ending an element when we have a simple value
- * that has qualifiers.
- *
- * Qualifiers aren't all that common, and we don't do anything
- * with them.
- *
- * @param $elm String namespace and element
- */
+ * End element while in MODE_QDESC
+ * mostly when ending an element when we have a simple value
+ * that has qualifiers.
+ *
+ * Qualifiers aren't all that common, and we don't do anything
+ * with them.
+ *
+ * @param $elm String namespace and element
+ */
private function endElementModeQDesc( $elm ) {
if ( $elm === self::NS_RDF . ' value' ) {
array_shift( $this->mode );
array_shift( $this->curItem );
}
-
-
}
/**
}
/**
- * Hit an opening element while in MODE_IGNORE
- *
- * XMP is extensible, so ignore any tag we don't understand.
- *
- * Mostly ignores, unless we encounter the element that we are ignoring.
- * in which case we add it to the item stack, so we can ignore things
- * that are nested, correctly.
- *
- * @param $elm String namespace . ' ' . tag name
- */
+ * Hit an opening element while in MODE_IGNORE
+ *
+ * XMP is extensible, so ignore any tag we don't understand.
+ *
+ * Mostly ignores, unless we encounter the element that we are ignoring.
+ * in which case we add it to the item stack, so we can ignore things
+ * that are nested, correctly.
+ *
+ * @param $elm String namespace . ' ' . tag name
+ */
private function startElementModeIgnore( $elm ) {
if ( $elm === $this->curItem[0] ) {
array_unshift( $this->curItem, $elm );
}
/**
- * Start element in MODE_BAG (unordered array)
- * this should always be <rdf:Bag>
- *
- * @param $elm String namespace . ' ' . tag
- * @throws MWException if we have an element that's not <rdf:Bag>
- */
+ * Start element in MODE_BAG (unordered array)
+ * this should always be <rdf:Bag>
+ *
+ * @param $elm String namespace . ' ' . tag
+ * @throws MWException if we have an element that's not <rdf:Bag>
+ */
private function startElementModeBag( $elm ) {
if ( $elm === self::NS_RDF . ' Bag' ) {
array_unshift( $this->mode, self::MODE_LI );
}
/**
- * Start element in MODE_SEQ (ordered array)
- * this should always be <rdf:Seq>
- *
- * @param $elm String namespace . ' ' . tag
- * @throws MWException if we have an element that's not <rdf:Seq>
- */
+ * Start element in MODE_SEQ (ordered array)
+ * this should always be <rdf:Seq>
+ *
+ * @param $elm String namespace . ' ' . tag
+ * @throws MWException if we have an element that's not <rdf:Seq>
+ */
private function startElementModeSeq( $elm ) {
if ( $elm === self::NS_RDF . ' Seq' ) {
array_unshift( $this->mode, self::MODE_LI );
}
/**
- * Start element in MODE_LANG (language alternative)
- * this should always be <rdf:Alt>
- *
- * This tag tends to be used for metadata like describe this
- * picture, which can be translated into multiple languages.
- *
- * XMP supports non-linguistic alternative selections,
- * which are really only used for thumbnails, which
- * we don't care about.
- *
- * @param $elm String namespace . ' ' . tag
- * @throws MWException if we have an element that's not <rdf:Alt>
- */
+ * Start element in MODE_LANG (language alternative)
+ * this should always be <rdf:Alt>
+ *
+ * This tag tends to be used for metadata like describe this
+ * picture, which can be translated into multiple languages.
+ *
+ * XMP supports non-linguistic alternative selections,
+ * which are really only used for thumbnails, which
+ * we don't care about.
+ *
+ * @param $elm String namespace . ' ' . tag
+ * @throws MWException if we have an element that's not <rdf:Alt>
+ */
private function startElementModeLang( $elm ) {
if ( $elm === self::NS_RDF . ' Alt' ) {
array_unshift( $this->mode, self::MODE_LI_LANG );
}
/**
- * Start an element when in MODE_QDESC.
- * This generally happens when a simple element has an inner
- * rdf:Description to hold qualifier elements.
- *
- * For example in:
- * <exif:DigitalZoomRatio><rdf:Description><rdf:value>0/10</rdf:value>
- * <foo:someQualifier>Bar</foo:someQualifier> </rdf:Description>
- * </exif:DigitalZoomRatio>
- * Called when processing the <rdf:value> or <foo:someQualifier>.
- *
- * @param $elm String namespace and tag name separated by a space.
- *
- */
+ * Start an element when in MODE_QDESC.
+ * This generally happens when a simple element has an inner
+ * rdf:Description to hold qualifier elements.
+ *
+ * For example in:
+ * <exif:DigitalZoomRatio><rdf:Description><rdf:value>0/10</rdf:value>
+ * <foo:someQualifier>Bar</foo:someQualifier> </rdf:Description>
+ * </exif:DigitalZoomRatio>
+ * Called when processing the <rdf:value> or <foo:someQualifier>.
+ *
+ * @param $elm String namespace and tag name separated by a space.
+ *
+ */
private function startElementModeQDesc( $elm ) {
if ( $elm === self::NS_RDF . ' value' ) {
return; // do nothing
}
/**
- * opening element in MODE_LI
- * process elements of arrays.
- *
- * Example:
- * <exif:ISOSpeedRatings> <rdf:Seq> <rdf:li>64</rdf:li>
- * </rdf:Seq> </exif:ISOSpeedRatings>
- * This method is called when we hit the <rdf:li> element.
- *
- * @param $elm String: namespace . ' ' . tagname
- * @param $attribs Array: Attributes. (needed for BAGSTRUCTS)
- * @throws MWException if gets a tag other than <rdf:li>
- */
+ * opening element in MODE_LI
+ * process elements of arrays.
+ *
+ * Example:
+ * <exif:ISOSpeedRatings> <rdf:Seq> <rdf:li>64</rdf:li>
+ * </rdf:Seq> </exif:ISOSpeedRatings>
+ * This method is called when we hit the <rdf:li> element.
+ *
+ * @param $elm String: namespace . ' ' . tagname
+ * @param $attribs Array: Attributes. (needed for BAGSTRUCTS)
+ * @throws MWException if gets a tag other than <rdf:li>
+ */
private function startElementModeLi( $elm, $attribs ) {
if ( ( $elm ) !== self::NS_RDF . ' li' ) {
throw new MWException( "<rdf:li> expected but got $elm." );
}
/**
- * Opening element in MODE_LI_LANG.
- * process elements of language alternatives
- *
- * Example:
- * <dc:title> <rdf:Alt> <rdf:li xml:lang="x-default">My house
- * </rdf:li> </rdf:Alt> </dc:title>
- *
- * This method is called when we hit the <rdf:li> element.
- *
- * @param $elm String namespace . ' ' . tag
- * @param $attribs array array of elements (most importantly xml:lang)
- * @throws MWException if gets a tag other than <rdf:li> or if no xml:lang
- */
+ * Opening element in MODE_LI_LANG.
+ * process elements of language alternatives
+ *
+ * Example:
+ * <dc:title> <rdf:Alt> <rdf:li xml:lang="x-default">My house
+ * </rdf:li> </rdf:Alt> </dc:title>
+ *
+ * This method is called when we hit the <rdf:li> element.
+ *
+ * @param $elm String namespace . ' ' . tag
+ * @param $attribs array array of elements (most importantly xml:lang)
+ * @throws MWException if gets a tag other than <rdf:li> or if no xml:lang
+ */
private function startElementModeLiLang( $elm, $attribs ) {
if ( $elm !== self::NS_RDF . ' li' ) {
throw new MWException( __METHOD__ . " <rdf:li> expected but got $elm." );
$this->mode[0] = self::MODE_QDESC;
}
foreach ( $attribs as $name => $val ) {
-
-
if ( strpos( $name, ' ' ) === false ) {
// This shouldn't happen, but so far some old software forgets namespace
// on rdf:about.
}
/**
- * Given an extracted value, save it to results array
- *
- * note also uses $this->ancestorStruct and
- * $this->processingArray to determine what name to
- * save the value under. (in addition to $tag).
- *
- * @param $ns String namespace of tag this is for
- * @param $tag String tag name
- * @param $val String value to save
- */
+ * Given an extracted value, save it to results array
+ *
+ * note also uses $this->ancestorStruct and
+ * $this->processingArray to determine what name to
+ * save the value under. (in addition to $tag).
+ *
+ * @param $ns String namespace of tag this is for
+ * @param $tag String tag name
+ * @param $val String value to save
+ */
private function saveValue( $ns, $tag, $val ) {
$info =& $this->items[$ns][$tag];
*/
/**
-* This class is just a container for a big array
-* used by XMPReader to determine which XMP items to
-* extract.
-*/
+ * This class is just a container for a big array
+ * used by XMPReader to determine which XMP items to
+ * extract.
+ */
class XMPInfo {
/** get the items array
* @return Array XMP item configuration array.
- */
+ */
public static function getItems ( ) {
if( !self::$ranHooks ) {
// This is for if someone makes a custom metadata extension.
static private $ranHooks = false;
/**
- * XMPInfo::$items keeps a list of all the items
- * we are interested to extract, as well as
- * information about the item like what type
- * it is.
- *
- * Format is an array of namespaces,
- * each containing an array of tags
- * each tag is an array of information about the
- * tag, including:
- * * map_group - what group (used for precedence during conflicts)
- * * mode - What type of item (self::MODE_SIMPLE usually, see above for all values)
- * * validate - method to validate input. Could also post-process the input. A string value is assumed to be a static method of XMPValidate. Can also take a array( 'className', 'methodName' ).
- * * choices - array of potential values (format of 'value' => true ). Only used with validateClosed
- * * rangeLow and rangeHigh - alternative to choices for numeric ranges. Again for validateClosed only.
- * * children - for MODE_STRUCT items, allowed children.
- * * structPart - Indicates that this element can only appear as a member of a structure.
- *
- * currently this just has a bunch of exif values as this class is only half-done
- */
-
+ * XMPInfo::$items keeps a list of all the items
+ * we are interested to extract, as well as
+ * information about the item like what type
+ * it is.
+ *
+ * Format is an array of namespaces,
+ * each containing an array of tags
+ * each tag is an array of information about the
+ * tag, including:
+ * * map_group - what group (used for precedence during conflicts)
+ * * mode - What type of item (self::MODE_SIMPLE usually, see above for all values)
+ * * validate - method to validate input. Could also post-process the input. A string value is assumed to be a static method of XMPValidate. Can also take a array( 'className', 'methodName' ).
+ * * choices - array of potential values (format of 'value' => true ). Only used with validateClosed
+ * * rangeLow and rangeHigh - alternative to choices for numeric ranges. Again for validateClosed only.
+ * * children - for MODE_STRUCT items, allowed children.
+ * * structPart - Indicates that this element can only appear as a member of a structure.
+ *
+ * currently this just has a bunch of exif values as this class is only half-done
+ */
static private $items = array(
'http://ns.adobe.com/exif/1.0/' => array(
'ApertureValue' => array(
*/
/**
-* This contains some static methods for
-* validating XMP properties. See XMPInfo and XMPReader classes.
-*
-* Each of these functions take the same parameters
-* * an info array which is a subset of the XMPInfo::items array
-* * A value (passed as reference) to validate. This can be either a
-* simple value or an array
-* * A boolean to determine if this is validating a simple or complex values
-*
-* It should be noted that when an array is being validated, typically the validation
-* function is called once for each value, and then once at the end for the entire array.
-*
-* These validation functions can also be used to modify the data. See the gps and flash one's
-* for example.
-*
-* @see http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart1.pdf starting at pg 28
-* @see http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart2.pdf starting at pg 11
-*/
+ * This contains some static methods for
+ * validating XMP properties. See XMPInfo and XMPReader classes.
+ *
+ * Each of these functions take the same parameters
+ * * an info array which is a subset of the XMPInfo::items array
+ * * A value (passed as reference) to validate. This can be either a
+ * simple value or an array
+ * * A boolean to determine if this is validating a simple or complex values
+ *
+ * It should be noted that when an array is being validated, typically the validation
+ * function is called once for each value, and then once at the end for the entire array.
+ *
+ * These validation functions can also be used to modify the data. See the gps and flash one's
+ * for example.
+ *
+ * @see http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart1.pdf starting at pg 28
+ * @see http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart2.pdf starting at pg 11
+ */
class XMPValidate {
/**
- * function to validate boolean properties ( True or False )
- *
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate boolean properties ( True or False )
+ *
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateBoolean( $info, &$val, $standalone ) {
if ( !$standalone ) {
// this only validates standalone properties, not arrays, etc
}
/**
- * function to validate rational properties ( 12/10 )
- *
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate rational properties ( 12/10 )
+ *
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateRational( $info, &$val, $standalone ) {
if ( !$standalone ) {
// this only validates standalone properties, not arrays, etc
}
/**
- * function to validate rating properties -1, 0-5
- *
- * if its outside of range put it into range.
- *
- * @see MWG spec
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate rating properties -1, 0-5
+ *
+ * if its outside of range put it into range.
+ *
+ * @see MWG spec
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateRating( $info, &$val, $standalone ) {
if ( !$standalone ) {
// this only validates standalone properties, not arrays, etc
}
/**
- * function to validate integers
- *
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate integers
+ *
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateInteger( $info, &$val, $standalone ) {
if ( !$standalone ) {
// this only validates standalone properties, not arrays, etc
}
/**
- * function to validate properties with a fixed number of allowed
- * choices. (closed choice)
- *
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate properties with a fixed number of allowed
+ * choices. (closed choice)
+ *
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateClosed( $info, &$val, $standalone ) {
if ( !$standalone ) {
// this only validates standalone properties, not arrays, etc
}
/**
- * function to validate and modify flash structure
- *
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate and modify flash structure
+ *
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateFlash( $info, &$val, $standalone ) {
if ( $standalone ) {
// this only validates flash structs, not individual properties
}
/**
- * function to validate LangCode properties ( en-GB, etc )
- *
- * This is just a naive check to make sure it somewhat looks like a lang code.
- *
- * @see rfc 3066
- * @see http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart1.pdf page 30 (section 8.2.2.5)
- *
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate LangCode properties ( en-GB, etc )
+ *
+ * This is just a naive check to make sure it somewhat looks like a lang code.
+ *
+ * @see rfc 3066
+ * @see http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart1.pdf page 30 (section 8.2.2.5)
+ *
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateLangCode( $info, &$val, $standalone ) {
if ( !$standalone ) {
// this only validates standalone properties, not arrays, etc
}
/**
- * function to validate date properties, and convert to (partial) Exif format.
- *
- * Dates can be one of the following formats:
- * YYYY
- * YYYY-MM
- * YYYY-MM-DD
- * YYYY-MM-DDThh:mmTZD
- * YYYY-MM-DDThh:mm:ssTZD
- * YYYY-MM-DDThh:mm:ss.sTZD
- *
- * @param $info Array information about current property
- * @param &$val Mixed current value to validate. Converts to TS_EXIF as a side-effect.
- * in cases where there's only a partial date, it will give things like
- * 2011:04.
- * @param $standalone Boolean if this is a simple property or array
- */
+ * function to validate date properties, and convert to (partial) Exif format.
+ *
+ * Dates can be one of the following formats:
+ * YYYY
+ * YYYY-MM
+ * YYYY-MM-DD
+ * YYYY-MM-DDThh:mmTZD
+ * YYYY-MM-DDThh:mm:ssTZD
+ * YYYY-MM-DDThh:mm:ss.sTZD
+ *
+ * @param $info Array information about current property
+ * @param &$val Mixed current value to validate. Converts to TS_EXIF as a side-effect.
+ * in cases where there's only a partial date, it will give things like
+ * 2011:04.
+ * @param $standalone Boolean if this is a simple property or array
+ */
public static function validateDate( $info, &$val, $standalone ) {
if ( !$standalone ) {
// this only validates standalone properties, not arrays, etc
return;
}
-
// Extra check for empty string necessary due to TZ but no second case.
$stripSeconds = false;
if ( !isset( $res[6] ) || $res[6] === '' ) {
$z >>= $length;
# Add in the free bits from subsequent bytes
- for ( $i=1; $i<$length; $i++ ) {
+ for ( $i=1; $i < $length; $i++ ) {
$z <<= 6;
$z |= ord( $char[$i] ) & 0x3f;
}
return true;
}
- $uRTT = ceil( 1e6 * ( microtime( true ) - $timestamp ) ); // estimate RTT (us)
+ $uRTT = ceil( 1e6 * ( microtime( true ) - $timestamp ) ); // estimate RTT (us)
$sleep = 2*$uRTT; // rough time to do get()+set()
- $locked = false; // lock acquired
+ $locked = false; // lock acquired
$attempts = 0; // failed attempts
do {
if ( ++$attempts >= 3 && $sleep <= 1e6 ) {
// }}}
-
/**
* Command statistics
*
* @access private
*/
function _load_items( $sock, &$ret, &$casToken = null ) {
+ $results = array();
+
while ( 1 ) {
$decl = $this->_fgets( $sock );
+
if( $decl === false ) {
+ /*
+ * If nothing can be read, something is wrong because we know exactly when
+ * to stop reading (right after "END") and we return right after that.
+ */
return false;
- } elseif ( $decl == "END" ) {
- return true;
} elseif ( preg_match( '/^VALUE (\S+) (\d+) (\d+) (\d+)$/', $decl, $match ) ) {
- list( $rkey, $flags, $len, $casToken ) = array( $match[1], $match[2], $match[3], $match[4] );
- $data = $this->_fread( $sock, $len + 2 );
- if ( $data === false ) {
- return false;
- }
- if ( substr( $data, -2 ) !== "\r\n" ) {
- $this->_handle_error( $sock,
- 'line ending missing from data block from $1' );
+ /*
+ * Read all data returned. This can be either one or multiple values.
+ * Save all that data (in an array) to be processed later: we'll first
+ * want to continue reading until "END" before doing anything else,
+ * to make sure that we don't leave our client in a state where it's
+ * output is not yet fully read.
+ */
+ $results[] = array(
+ $match[1], // rkey
+ $match[2], // flags
+ $match[3], // len
+ $match[4], // casToken
+ $this->_fread( $sock, $match[3] + 2 ), // data
+ );
+ } elseif ( $decl == "END" ) {
+ if ( count( $results ) == 0 ) {
return false;
}
- $data = substr( $data, 0, -2 );
- $ret[$rkey] = $data;
- if ( $this->_have_zlib && $flags & self::COMPRESSED ) {
- $ret[$rkey] = gzuncompress( $ret[$rkey] );
- }
+ /**
+ * All data has been read, time to process the data and build
+ * meaningful return values.
+ */
+ foreach ( $results as $vars ) {
+ list( $rkey, $flags, $len, $casToken, $data ) = $vars;
+
+ if ( $data === false || substr( $data, -2 ) !== "\r\n" ) {
+ $this->_handle_error( $sock,
+ 'line ending missing from data block from $1' );
+ return false;
+ }
+ $data = substr( $data, 0, -2 );
+ $ret[$rkey] = $data;
+
+ if ( $this->_have_zlib && $flags & self::COMPRESSED ) {
+ $ret[$rkey] = gzuncompress( $ret[$rkey] );
+ }
- if ( $flags & self::SERIALIZED ) {
- $ret[$rkey] = unserialize( $ret[$rkey] );
+ /*
+ * This unserialize is the exact reason that we only want to
+ * process data after having read until "END" (instead of doing
+ * this right away): "unserialize" can trigger outside code:
+ * in the event that $ret[$rkey] is a serialized object,
+ * unserializing it will trigger __wakeup() if present. If that
+ * function attempted to read from memcached (while we did not
+ * yet read "END"), these 2 calls would collide.
+ */
+ if ( $flags & self::SERIALIZED ) {
+ $ret[$rkey] = unserialize( $ret[$rkey] );
+ }
}
+ return true;
} else {
$this->_handle_error( $sock, 'Error parsing response from $1' );
return false;
// }}}
}
-
// }}}
class MemCachedClientforWiki extends MWMemcached {
*
* @file
*/
+
class RedisBagOStuff extends BagOStuff {
/** @var RedisConnectionPool */
protected $redisPool;
} else {
/*
* We must keep a separate connection to MySQL in order to avoid deadlocks
- * However, SQLite has an opposite behaviour. And PostgreSQL needs to know
+ * However, SQLite has an opposite behavior. And PostgreSQL needs to know
* if we are in transaction or no
*/
if ( wfGetDB( DB_MASTER )->getType() == 'mysql' ) {
return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw );
}
-
/**
* Given a title, return the namespace name that would be given by the
* corresponding magic word
$this->lang = $lang;
$this->monthNames = $this->getMonthRegex();
- for ( $i=1; $i<=12; $i++ ) {
+ for ( $i = 1; $i <= 12; $i++ ) {
$this->xMonths[$this->lang->lc( $this->lang->getMonthName( $i ) )] = $i;
$this->xMonths[$this->lang->lc( $this->lang->getMonthAbbreviation( $i ) )] = $i;
}
} else {
$preference = self::NONE;
}
- for ( $i=1; $i<=self::LAST; $i++ ) {
+ for ( $i = 1; $i <= self::LAST; $i++ ) {
$this->mSource = $i;
if ( isset ( $this->rules[$preference][$i] ) ) {
# Specific rules
$bits = array();
$key = $this->keys[$this->mSource];
- for ( $p=0; $p < strlen( $key ); $p++ ) {
+ for ( $p = 0; $p < strlen( $key ); $p++ ) {
if ( $key[$p] != ' ' ) {
$bits[$key[$p]] = $matches[$p+1];
}
$bits['d'] = sprintf( '%02d', $bits['j'] );
}
- for ( $p=0; $p < strlen( $format ); $p++ ) {
+ for ( $p = 0; $p < strlen( $format ); $p++ ) {
$char = $format[$p];
switch ( $char ) {
case 'd': # ISO day of month
}
}
-
if( !$linkBatch->isEmpty() ) {
// construct query
$dbr = wfGetDB( DB_SLAVE );
*/
function replaceTextCallback( $matches ) {
$type = $matches[1];
- $key = $matches[2];
+ $key = $matches[2];
if( $type == 'LINK' ) {
list( $ns, $index ) = explode( ':', $key, 2 );
if( isset( $this->internals[$ns][$index]['text'] ) ) {
var $mFunctionHooks = array();
var $mFunctionSynonyms = array( 0 => array(), 1 => array() );
var $mFunctionTagHooks = array();
- var $mStripList = array();
- var $mDefaultStripList = array();
+ var $mStripList = array();
+ var $mDefaultStripList = array();
var $mVarCache = array();
var $mImageParams = array();
var $mImageParamsMagicArray = array();
* string constructs.
*
* Must not consist of all title characters, or else it will change
- * the behaviour of <nowiki> in a link.
+ * the behavior of <nowiki> in a link.
*/
$this->mUniqPrefix = "\x7fUNIQ" . self::getRandomString();
$this->mStripState = new StripState( $this->mUniqPrefix );
-
# Clear these on every parse, bug 4549
$this->mTplExpandCache = $this->mTplRedirCache = $this->mTplDomCache = array();
}
if ( count( $p ) > 5 ) {
# comment
- $element = $p[4];
+ $element = $p[4];
$attributes = '';
- $close = '';
- $inside = $p[5];
+ $close = '';
+ $inside = $p[5];
} else {
# tag
- $element = $p[1];
+ $element = $p[1];
$attributes = $p[2];
- $close = $p[3];
- $inside = $p[4];
+ $close = $p[3];
+ $inside = $p[4];
}
$marker = "$uniq_prefix-$element-" . sprintf( '%08X', $n++ ) . self::MARKER_SUFFIX;
array_push( $tr_history, false );
array_push( $td_history, false );
array_push( $last_tag_history, '' );
- } elseif ( $first_character === '|' || $first_character === '!' || substr( $line, 0, 2 ) === '|+' ) {
+ } elseif ( $first_character === '|' || $first_character === '!' || substr( $line, 0, 2 ) === '|+' ) {
# This might be cell elements, td, th or captions
if ( substr( $line, 0, 2 ) === '|+' ) {
$first_character = '+';
return $text . $trail;
}
-
/**
* Parse headers and return html
*
wfProfileOut( __METHOD__ . "-might_be_img" );
}
- $wasblank = ( $text == '' );
+ $wasblank = ( $text == '' );
if ( $wasblank ) {
$text = $link;
} else {
{
# Bug 529: if the template begins with a table or block-level
# element, it should be treated as beginning a new line.
- # This behaviour is somewhat controversial.
+ # This behavior is somewhat controversial.
$text = "\n" . $text;
}
# Increase TOC level
$toclevel++;
$sublevelCount[$toclevel] = 0;
- if ( $toclevel<$wgMaxTocLevel ) {
+ if ( $toclevel < $wgMaxTocLevel ) {
$prevtoclevel = $toclevel;
$toc .= Linker::tocIndent();
$numVisible++;
if ( $i == 0 ) {
$toclevel = 1;
}
- if ( $toclevel<$wgMaxTocLevel ) {
+ if ( $toclevel < $wgMaxTocLevel ) {
if ( $prevtoclevel < $wgMaxTocLevel ) {
# Unindent only if the previous toc level was shown :p
$toc .= Linker::tocUnindent( $prevtoclevel - $toclevel );
}
} else {
# No change in level, end TOC line
- if ( $toclevel<$wgMaxTocLevel ) {
+ if ( $toclevel < $wgMaxTocLevel ) {
$toc .= Linker::tocLineEnd();
}
}
$confstr .= '*';
}
-
// Space assigned for the stubthreshold but unused
// since it disables the parser cache, its value will always
// be 0 when this function is called by parsercache.
return $this->mProperties;
}
-
/**
* Returns the options from its ParserOptions which have been taken
* into account to produce this output or false if not available.
*/
function getChildrenOfType( $type );
-
/**
* Returns the length of the array, or false if this is not an array-type node
*/
if ( $equalsLength > 0 ) {
if ( $searchStart - $equalsLength == $piece->startPos ) {
// This is just a single string of equals signs on its own line
- // Replicate the doHeadings behaviour /={count}(.+)={count}/
+ // Replicate the doHeadings behavior /={count}(.+)={count}/
// First find out how many equals signs there really are (don't stop at 6)
$count = $equalsLength;
if ( $count < 3 ) {
*/
var $depth;
-
/**
* Construct a new preprocessor frame.
* @param $preprocessor Preprocessor The parent preprocessor
if ( $equalsLength > 0 ) {
if ( $searchStart - $equalsLength == $piece->startPos ) {
// This is just a single string of equals signs on its own line
- // Replicate the doHeadings behaviour /={count}(.+)={count}/
+ // Replicate the doHeadings behavior /={count}(.+)={count}/
// First find out how many equals signs there really are (don't stop at 6)
$count = $equalsLength;
if ( $count < 3 ) {
*/
var $depth;
-
/**
* Construct a new preprocessor frame.
* @param $preprocessor Preprocessor: the parent preprocessor
$width = 140;
$nameWidth = $width - 65;
- $format = "%-{$nameWidth}s %6d %13.3f %13.3f %13.3f%% %9d (%13.3f -%13.3f) [%d]\n";
+ $format = "%-{$nameWidth}s %6d %13.3f %13.3f %13.3f%% %9d (%13.3f -%13.3f) [%d]\n";
$titleFormat = "%-{$nameWidth}s %6s %13s %13s %13s %9s\n";
$prof = "\nProfiling data\n";
$prof .= sprintf( $titleFormat, 'Name', 'Calls', 'Total', 'Each', '%', 'Mem' );
class ProfilerSimple extends Profiler {
var $mMinimumTime = 0;
- var $zeroEntry = array( 'cpu'=> 0.0, 'cpu_sq' => 0.0, 'real' => 0.0, 'real_sq' => 0.0, 'count' => 0 );
+ var $zeroEntry = array( 'cpu' => 0.0, 'cpu_sq' => 0.0, 'real' => 0.0, 'real_sq' => 0.0, 'count' => 0 );
var $errorEntry;
public function isPersistent() {
$this->registerTestModules();
}
-
wfProfileOut( __METHOD__ );
}
// to propagate to clients quickly
// If there were errors, we also need a shorter expiry time so we can recover quickly
if ( is_null( $context->getVersion() ) || $errors ) {
- $maxage = $wgResourceLoaderMaxage['unversioned']['client'];
+ $maxage = $wgResourceLoaderMaxage['unversioned']['client'];
$smaxage = $wgResourceLoaderMaxage['unversioned']['server'];
// If a version was specified we can use a longer expiry time since changing
// version numbers causes cache misses
} else {
- $maxage = $wgResourceLoaderMaxage['versioned']['client'];
+ $maxage = $wgResourceLoaderMaxage['versioned']['client'];
$smaxage = $wgResourceLoaderMaxage['versioned']['server'];
}
if ( $context->getOnly() === 'styles' ) {
// Interpret request
// List of modules
$modules = $request->getVal( 'modules' );
- $this->modules = $modules ? self::expandModuleNames( $modules ) : array();
+ $this->modules = $modules ? self::expandModuleNames( $modules ) : array();
// Various parameters
- $this->skin = $request->getVal( 'skin' );
- $this->user = $request->getVal( 'user' );
- $this->debug = $request->getFuzzyBool( 'debug', $wgResourceLoaderDebug );
- $this->only = $request->getVal( 'only' );
- $this->version = $request->getVal( 'version' );
- $this->raw = $request->getFuzzyBool( 'raw' );
+ $this->skin = $request->getVal( 'skin' );
+ $this->user = $request->getVal( 'user' );
+ $this->debug = $request->getFuzzyBool( 'debug', $wgResourceLoaderDebug );
+ $this->only = $request->getVal( 'only' );
+ $this->version = $request->getVal( 'version' );
+ $this->raw = $request->getFuzzyBool( 'raw' );
$skinnames = Skin::getSkinNames();
// If no skin is specified, or we don't recognize the skin, use the default skin
public function getLanguage() {
if ( $this->language === null ) {
global $wgLang;
- $this->language = $this->request->getVal( 'lang' );
+ $this->language = $this->request->getVal( 'lang' );
if ( !$this->language ) {
$this->language = $wgLang->getCode();
}
return false;
}
-
/** @var JSParser lazy-initialized; use self::javaScriptParser() */
private static $jsParser;
private static $parseCacheVersion = 1;
if ( strval( $script ) !== '' ) {
$script = $this->validateScriptFile( $titleText, $script );
if ( strpos( $titleText, '*/' ) === false ) {
- $scripts .= "/* $titleText */\n";
+ $scripts .= "/* $titleText */\n";
}
$scripts .= $script . "\n";
}
$styles[$media] = array();
}
if ( strpos( $titleText, '*/' ) === false ) {
- $style = "/* $titleText */\n" . $style;
+ $style = "/* $titleText */\n" . $style;
}
$styles[$media][] = $style;
}
}
}
-
/**
* Item class for a archive table row by ar_rev_id -- actually
* used via RevDel_RevisionList.
$title = Title::newFromText( $searchterm );
-
# Entering an IP address goes to the contributions page
if ( $wgEnableSearchContributorsByIP ) {
if ( ( $title->getNamespace() == NS_USER && User::isIP( $title->getText() ) )
}
}
-
# Entering a user goes to the user page whether it's there or not
if ( $title->getNamespace() == NS_USER ) {
return $title;
# # Some search engines may bail out if too many matches are found
}
-
/**
* @todo FIXME: This class is horribly factored. It would probably be better to
* have a useful base class to which you pass some standard information, then
}
$spat .= '/';
$textExt = array(); // text extracts
- $otherExt = array(); // other extracts
+ $otherExt = array(); // other extracts
wfProfileIn( "$fname-split" );
$start = 0;
$textLen = strlen( $text );
return new MssqlSearchResultSet( $resultSet, $this->searchTerms );
}
-
/**
* Return a partial WHERE clause to exclude redirects, if so set
*
*/
function queryMain( $filteredTerm, $fulltext ) {
$match = $this->parseQuery( $filteredTerm, $fulltext );
- $page = $this->db->tableName( 'page' );
+ $page = $this->db->tableName( 'page' );
$searchindex = $this->db->tableName( 'searchindex' );
return 'SELECT page_id, page_namespace, page_title, ftindex.[RANK]' .
return new MySQLSearchResultSet( $resultSet, $this->searchTerms );
}
-
/**
* Return a partial WHERE clause to exclude redirects, if so set
* @return String
$this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
}
-
/**
* Picks which field to index on, depending on what type of query.
* @param $fulltext Boolean
}
}
-
$searchon = $this->db->addQuotes( ltrim( $searchon, ' &' ) );
$field = $this->getIndexField( $fulltext );
return " CONTAINS($field, $searchon, 1) > 0 ";
array() );
}
-
public static function legalSearchChars() {
return "\"" . parent::legalSearchChars();
}
return new SqliteSearchResultSet( $resultSet, $this->searchTerms, $total );
}
-
/**
* Return a partial WHERE clause to exclude redirects, if so set
* @return String
function getCountQuery( $filteredTerm, $fulltext ) {
$match = $this->parseQuery( $filteredTerm, $fulltext );
- $page = $this->db->tableName( 'page' );
+ $page = $this->db->tableName( 'page' );
$searchindex = $this->db->tableName( 'searchindex' );
return "SELECT COUNT(*) AS c " .
"FROM $page,$searchindex " .
return $page['title'];
}
-
/**
* Get normalization record for a given page title from an API response.
*
* @see Site::getPageUrl
*
* This implementation returns a URL constructed using the path returned by getLinkPath().
- * In addition to the default behaviour implemented by Site::getPageUrl(), this
+ * In addition to the default behavior implemented by Site::getPageUrl(), this
* method converts the $pageName to DBKey-format by replacing spaces with underscores
* before using it in the URL.
*
const PATH_LINK = 'link';
-
/**
* A version ID that identifies the serialization structure used by getSerializationData()
* and unserialize(). This is useful for constructing cache keys in cases where the cache relies
$this->lang = ( $langObj ? $langObj : $wgContLang );
$this->langcode = $this->lang->getCode();
- $this->foreign = $this->langcode != $wgContLang->getCode();
+ $this->foreign = $this->langcode != $wgContLang->getCode();
$request = $this->getRequest();
function formatValue( $field, $value ) {
switch( $field ) {
-
case 'am_title' :
-
$title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
- $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
+ $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
if( $this->mCurrentRow->am_customised ) {
$title = Linker::linkKnown( $title, $this->getLanguage()->lcfirst( $value ) );
global $wgScript;
$t = $this->getTitle();
- $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) );
+ $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) );
$out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
$out .= Html::hidden( 'title', $t->getPrefixedText() );
$out .= Xml::openElement( 'fieldset' );
Linker::link( $self, $this->msg( 'allpages' )->escaped() );
# Do we put a previous link ?
- if( isset( $prevTitle ) && $pt = $prevTitle->getText() ) {
+ if( isset( $prevTitle ) && $pt = $prevTitle->getText() ) {
$query = array( 'from' => $prevTitle->getText() );
if( $namespace )
*/
/**
- * A special page called by proxy_check.php to block open proxies
+ * A special page called by proxyCheck.php to block open proxies
*
* @ingroup SpecialPage
*/
private function makeForm() {
global $wgScript;
- $form = '<fieldset><legend>' . $this->msg( 'booksources-search-legend' )->escaped() . '</legend>';
+ $form = '<fieldset><legend>' . $this->msg( 'booksources-search-legend' )->escaped() . '</legend>';
$form .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
$form .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
$form .= '<p>' . Xml::inputLabel( $this->msg( 'booksources-isbn' )->text(), 'isbn', 'isbn', 20, $this->isbn );
$out->wrapWikiMsg( "<div class=\"error mw-confirmemail-pending\">\n$1\n</div>", 'confirmemail_pending' );
}
$out->addWikiMsg( 'confirmemail_text' );
- $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl() ) );
+ $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl() ) );
$form .= Html::hidden( 'token', $user->getEditToken() );
$form .= Xml::submitButton( $this->msg( 'confirmemail_send' )->text() );
$form .= Xml::closeElement( 'form' );
}
$out->preventClickjacking( $pager->getPreventClickjacking() );
-
# Show the appropriate "footer" message - WHOIS tools, etc.
if ( $this->opts['contribs'] == 'newbie' ) {
$message = 'sp-contributions-footer-newbies';
);
}
-
function sortDescending() {
return false;
}
$file = wfFindFile( $title );
if ( $file && $file->exists() ) {
- // Default behaviour: Use the direct link to the file.
+ // Default behavior: Use the direct link to the file.
$url = $file->getURL();
$width = $request->getInt( 'width', -1 );
$height = $request->getInt( 'height', -1 );
* @author Brion Vibber
*/
-
/**
* Special:LinkSearch to search the external-links table.
* @ingroup SpecialPage
return $s;
}
-
/**
* Set page title and show header for this log type
* @param $type string
parent::execute( $par );
}
-
function formatResult( $skin, $result ) {
global $wgContLang;
? Title::newFromText( $newTitleText_bc )
: Title::makeTitleSafe( $newTitleTextNs, $newTitleTextMain );
-
$user = $this->getUser();
# Check rights
$msgName = 'movepage-moved-noredirect';
}
-
$out->addHTML( $this->msg( 'movepage-moved' )->rawParams( $oldLink,
$newLink )->params( $oldText, $newText )->parseAsBlock() );
$out->addWikiMsg( $msgName );
}
}
-
/**
* @ingroup SpecialPage Pager
*/
function namespacePrefixForm( $namespace = NS_MAIN, $from = '', $hideredirects = false ) {
global $wgScript;
- $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) );
+ $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) );
$out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
$out .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
$out .= Xml::openElement( 'fieldset' );
class SpecialProtectedpages extends SpecialPage {
protected $IdLevel = 'level';
- protected $IdType = 'type';
+ protected $IdType = 'type';
public function __construct() {
parent::__construct( 'Protectedpages' );
class SpecialProtectedtitles extends SpecialPage {
protected $IdLevel = 'level';
- protected $IdType = 'type';
+ protected $IdType = 'type';
public function __construct() {
parent::__construct( 'Protectedtitles' );
* @ingroup SpecialPage
*/
class RandomPage extends SpecialPage {
- private $namespaces; // namespaces to select pages from
+ private $namespaces; // namespaces to select pages from
protected $isRedir = false; // should the result be a redirect?
protected $extra = array(); // Extra SQL statements
return $this->rcOptions;
}
-
/**
* Main execution point
*
if( $opts['namespace'] !== '' ) {
$selectedNS = $dbr->addQuotes( $opts['namespace'] );
$operator = $opts['invert'] ? '!=' : '=';
- $boolean = $opts['invert'] ? 'AND' : 'OR';
+ $boolean = $opts['invert'] ? 'AND' : 'OR';
# namespace association (bug 2429)
if( !$opts['associated'] ) {
}
$dl = $lang->pipeList( $dl );
-
// show/hide links
$showhide = array( $this->msg( 'show' )->text(), $this->msg( 'hide' )->text() );
$filters = array(
}
/**
- * @return String: HTML
- */
+ * @return String: HTML
+ */
protected function buildCheckBoxes() {
$html = '<table>';
// If there is just one item, use checkboxes
if( $textMatches && $textMatches->hasSuggestion() ) {
$st = SpecialPage::getTitleFor( 'Search' );
- # mirror Go/Search behaviour of original request ..
+ # mirror Go/Search behavior of original request ..
$didYouMeanParams = array( 'search' => $textMatches->getSuggestionQuery() );
if( $this->fulltext != null ) {
$out->addHTML( $this->formHeader( $term, $num, $totalRes ) );
$out->addHtml( $this->getProfileForm( $this->profile, $term ) );
-
$out->addHtml( Xml::closeElement( 'form' ) );
$out->addHtml( "<div class='searchresults'>" );
return $text;
}
- private function getOtherStats( $stats ) {
- if ( !count( $stats ) )
- return '';
+ /**
+ * Conversion of external statistics into an internal representation
+ * Following a ([<header-message>][<item-message>] = number) pattern
+ *
+ * @param array $stats
+ * @return string
+ */
+ private function getOtherStats( array $stats ) {
+ $return = '';
- $return = Xml::openElement( 'tr' ) .
- Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-hooks' )->parse() ) .
- Xml::closeElement( 'tr' );
+ foreach( $stats as $header => $items ) {
+
+ // Identify the structure used
+ if ( is_array( $items ) ) {
- foreach( $stats as $name => $number ) {
- $name = htmlspecialchars( $name );
- $number = htmlspecialchars( $number );
+ // Ignore headers that are recursively set as legacy header
+ if ( $header !== 'statistics-header-hooks' ) {
+ $return .= $this->formatRowHeader( $header );
+ }
+
+ // Collect all items that belong to the same header
+ foreach( $items as $key => $value ) {
+ $name = $this->msg( $key )->inContentLanguage()->parse();
+ $number = htmlspecialchars( $value );
- $return .= $this->formatRow( $name, $this->getLanguage()->formatNum( $number ), array( 'class' => 'mw-statistics-hook' ) );
+ $return .= $this->formatRow( $name, $this->getLanguage()->formatNum( $number ), array( 'class' => 'mw-statistics-hook' ) );
+ }
+ } else {
+ // Create the legacy header only once
+ if ( $return === '' ) {
+ $return .= $this->formatRowHeader( 'statistics-header-hooks' );
+ }
+
+ // Recursively remap the legacy structure
+ $return .= $this->getOtherStats( array( 'statistics-header-hooks' => array( $header => $items ) ) );
+ }
}
return $return;
}
+
+ /**
+ * Format row header
+ *
+ * @param string $header
+ * @return string
+ */
+ private function formatRowHeader( $header ) {
+ return Xml::openElement( 'tr' ) .
+ Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( $header )->parse() ) .
+ Xml::closeElement( 'tr' );
+ }
}
// default for page_namespace is all content namespaces (if requestedNamespace is false)
// otherwise, page_namespace is requestedNamespace
'conds' => array ( 'cl_from IS NULL',
- 'page_namespace' => ( $this->requestedNamespace!==false ? $this->requestedNamespace : MWNamespace::getContentNamespaces() ),
+ 'page_namespace' => ( $this->requestedNamespace !== false ? $this->requestedNamespace : MWNamespace::getContentNamespaces() ),
'page_is_redirect' => 0 ),
'join_conds' => array ( 'categorylinks' => array (
'LEFT JOIN', 'cl_from = page_id' ) )
$makepage = false;
# Page already exists. Import the history, and if necessary
# we'll update the latest revision field in the record.
- $newid = 0;
- $pageId = $page->page_id;
- $previousRevId = $page->page_latest;
+ $newid = 0;
+ $pageId = $page->page_id;
+ $previousRevId = $page->page_latest;
# Get the time span of this page
$previousTimestamp = $dbw->selectField( 'revision', 'rev_timestamp',
array( 'rev_id' => $previousRevId ),
return Status::newFatal( "undeleterevdel" );
}
// Safe to insert now...
- $newid = $article->insertOn( $dbw );
+ $newid = $article->insertOn( $dbw );
$pageId = $newid;
} else {
// Check if a deleted revision will become the current revision...
}
}
- $newid = false;
+ $newid = false;
$pageId = $article->getId();
}
if ( $this->mAllowed ) {
# Slip in the hidden controls here
- $misc = Html::hidden( 'target', $this->mTarget );
+ $misc = Html::hidden( 'target', $this->mTarget );
$misc .= Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() );
$misc .= Xml::closeElement( 'form' );
$out->addHTML( $misc );
}
/** Misc variables **/
- public $mRequest; // The WebRequest or FauxRequest this form is supposed to handle
+ public $mRequest; // The WebRequest or FauxRequest this form is supposed to handle
public $mSourceType;
/**
public $mUploadClicked;
/** User input variables from the "description" section **/
- public $mDesiredDestName; // The requested target file name
+ public $mDesiredDestName; // The requested target file name
public $mComment;
public $mLicense;
/** Hidden variables **/
public $mDestWarningAck;
- public $mForReUpload; // The user followed an "overwrite this file" link
- public $mCancelUpload; // The user clicked "Cancel and return to upload form" button
+ public $mForReUpload; // The user followed an "overwrite this file" link
+ public $mCancelUpload; // The user clicked "Cancel and return to upload form" button
public $mTokenOk;
- public $mUploadSuccessful = false; // Subclasses can use this to determine whether a file was uploaded
+ public $mUploadSuccessful = false; // Subclasses can use this to determine whether a file was uploaded
/** Text injection points for hooks not using HTMLForm **/
public $uploadFormTextTop;
$this->mCopyrightStatus = $request->getText( 'wpUploadCopyStatus' );
$this->mCopyrightSource = $request->getText( 'wpUploadSource' );
-
$this->mForReUpload = $request->getBool( 'wpForReUpload' ); // updating a file
$this->mCancelUpload = $request->getCheck( 'wpCancelUpload' )
|| $request->getCheck( 'wpReUpload' ); // b/w compat
}
}
-
/**
* Provides output to the user for a result of UploadBase::verifyUpload
*
$out = $this->getOutput();
$out->addJsConfigVars( $scriptVars );
-
$out->addModules( array(
'mediawiki.action.edit', // For <charinsert> support
'mediawiki.legacy.upload', // Old form stuff...
if( !$status->isGood() ) {
$error = $this->getOutput()->parse( $status->getWikiText() );
$this->mainLoginForm( $error );
- return false;
+ return;
}
$u = $status->getValue();
// faces etc will probably just fail cleanly here.
$retval = self::RESET_PASS;
} else {
- $retval = ( $this->mPassword == '' ) ? self::EMPTY_PASS : self::WRONG_PASS;
+ $retval = ( $this->mPassword == '' ) ? self::EMPTY_PASS : self::WRONG_PASS;
}
} elseif ( $wgBlockDisablesLogin && $u->isBlocked() ) {
// If we've enabled it, make it so that a blocked user cannot login
}
}
+ /**
+ * @param $error string
+ */
function resetLoginForm( $error ) {
$this->getOutput()->addHTML( Xml::element( 'p', array( 'class' => 'error' ), $error ) );
$reset = new SpecialChangePassword();
return $result;
}
-
/**
* Run any hooks registered for logins, then HTTP redirect to
* $this->mReturnTo (or Main Page if that's undefined). Formerly we had a
* User::isBlockedFromCreateAccount(), which gets this block, ignores the 'hardblock'
* setting on blocks (bug 13611).
* @param $block Block the block causing this error
+ * @throws ErrorPageError
*/
function userBlockedMessage( Block $block ) {
# Let's be nice about this, it's likely that this feature will be used
* Create a language selector link for a particular language
* Links back to this page preserving type and returnto
*
- * @param $text Link text
- * @param $lang Language code
+ * @param $text string Link text
+ * @param $lang string Language code
* @return string
*/
function makeLanguageSelectorLink( $text, $lang ) {
return array( $add, $remove );
}
-
/**
* Add a rights log entry for an action.
*/
return $repo->getHeadSHA1();
}
-
/**
* Get the list of entry points and their URLs
* @return string Wikitext
# Up estimate of watched items by 15% to compensate for talk pages...
-
# Toggles
if( $values['hideOwn'] ) {
$conds[] = 'rc_user != ' . $user->getId();
}
$this->mFilteredName = $nt->getDBkey();
-
-
/**
* We'll want to blacklist against *any* 'extension', and use
* only the final one for the whitelist.
$ext = array( $this->mFinalExtension );
}
}
-
}
/* Don't allow users to override the blacklist (check file extension) */
}
# use set to add a remote / data / script target to an element
- if( $strippedElement == 'set' && $stripped == 'to' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
+ if( $strippedElement == 'set' && $stripped == 'to' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
wfDebug( __METHOD__ . ": Found svg setting attibute to '$value' in uploaded file.\n" );
return true;
}
-
# use handler attribute with remote / data / script
- if( $stripped == 'handler' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
+ if( $stripped == 'handler' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
wfDebug( __METHOD__ . ": Found svg setting handler with remote/data/script '$attrib'='$value' in uploaded file.\n" );
return true;
}
}
}
+ // Check for files with the same name but a different extension
+ $similarFiles = RepoGroup::singleton()->getLocalRepo()->findFilesByPrefix(
+ "{$partname}.", 1 );
+ if ( count( $similarFiles ) ) {
+ return array(\r
+ 'warning' => 'exists-normalized',\r
+ 'file' => $file,\r
+ 'normalizedFile' => $similarFiles[0],\r
+ );
+ }
+
if ( self::isThumbName( $file->getName() ) ) {
# Check for filenames like 50px- or 180px-, these are mostly thumbnails
$nt_thb = Title::newFromText( substr( $partname, strpos( $partname, '-' ) + 1 ) . '.' . $extension, NS_FILE );
}
}
-
foreach( self::getFilenamePrefixBlacklist() as $prefix ) {
if ( substr( $partname, 0, strlen( $prefix ) ) == $prefix ) {
return array(
return $this->removeFileNoAuth( $key );
}
-
/**
* Remove a file (see removeFile), but doesn't check ownership first.
*
}
}
+ /**
+ * Get the ordered list of fallback languages, ending with the fallback
+ * language chain for the site language.
+ *
+ * @since 1.21
+ * @param $code string Language code
+ * @return array
+ */
+ public static function getFallbacksIncludingSiteLanguage( $code ) {
+ global $wgLanguageCode;
+
+ // Usually, we will only store a tiny number of fallback chains, so we
+ // keep them in static memory.
+ static $fallbackLanguageCache = array();
+ $cacheKey = "{$code}-{$wgLanguageCode}";
+
+ if ( !array_key_exists( $cacheKey, $fallbackLanguageCache ) ) {
+ $fallbacks = self::getFallbacksFor( $code );
+
+ // Take the final 'en' off of the array before splicing
+ if ( end( $fallbacks ) === 'en' ) {
+ array_pop( $fallbacks );
+ }
+ // Append the site's fallback chain
+ $siteFallbacks = self::getFallbacksFor( $wgLanguageCode );
+
+ // Eliminate any languages already included in the chain
+ $siteFallbacks = array_intersect( array_diff( $siteFallbacks, $fallbacks ), $siteFallbacks );
+ if ( $siteFallbacks ) {
+ $fallbacks = array_merge( $fallbacks, $siteFallbacks );
+ }
+ if ( end( $fallbacks ) !== 'en' ) {
+ $fallbacks[] = 'en';
+ }
+ $fallbackLanguageCache[$cacheKey] = $fallbacks;
+ }
+ return $fallbackLanguageCache[$cacheKey];
+ }
+
/**
* Get all messages for a given language
* WARNING: this may take a long time. If you just need all message *keys*
'gotaccount' => "Het u reeds 'n rekening? '''$1'''.",
'gotaccountlink' => 'Teken in',
'userlogin-resetlink' => 'U aanmeld besonderhede vergeet?',
-'createaccountmail' => 'deur e-pos',
+'createaccountmail' => "Gebruik 'n tydelike lukrake wagwoord en stuur dit na die e-posadres hier onder",
'createaccountreason' => 'Rede:',
'badretype' => 'Die ingetikte wagwoorde is nie dieselfde nie.',
'userexists' => "Die gebruikersnaam wat u gekies het is reeds geneem.
'loginlanguagelabel' => 'Taal: $1',
'suspicious-userlogout' => "U versoek om af te teken is geïgnoreer omdat dit lyk asof dit deur 'n gebreekte webleser of instaanbediener gestuur is.",
-# E-mail sending
+# Email sending
'php-mail-error-unknown' => 'Onbekende fout in PHP se mail()-funksie',
'user-mail-no-addy' => "Geprobeer om e-pos te stuur sonder 'n e-posadres.",
'user-mail-no-body' => "Daar is probeer om 'n leë of 'n onredelike kort boodskap te stuur.",
'search-interwiki-default' => '$1 resultate:',
'search-interwiki-more' => '(meer)',
'search-relatedarticle' => 'Verwante',
-'mwsuggest-disable' => 'Deaktiveer AJAX-voorstelle',
+'mwsuggest-disable' => 'Deaktiveer soek-voorstelle',
'searcheverything-enable' => 'Soek in alle naamruimtes',
'searchrelated' => 'verwante',
'searchall' => 'alle',
'prefs-displaywatchlist' => 'Weergaweopsies',
'prefs-diffs' => 'Verskille',
-# User preference: e-mail validation using jQuery
+# User preference: email validation using jQuery
'email-address-validity-valid' => 'Die e-posadres lyk geldig',
'email-address-validity-invalid' => "Verskaf 'n geldige e-posadres",
Hulle moet gewysig word om eerder direk na die regte onderwerpe te skakel.<br />
'n Bladsy word beskou as 'n dubbelsinnigheidsbladsy as dit 'n sjabloon bevat wat geskakel is vanaf [[MediaWiki:Disambiguationspage]]",
+'pageswithprop' => "Blaaie met 'n bladsy-eienskap",
+'pageswithprop-text' => "Hierdie bladsy lys blaaie met 'n bepaalde blady-eienskap.",
+'pageswithprop-prop' => 'Naam van die eienskap:',
+
'doubleredirects' => 'Dubbele aansture',
'doubleredirectstext' => 'Hierdie lys bevat bladsye wat aansture na ander aanstuurblaaie is.
Elke ry bevat skakels na die eerste en die tweede aanstuur, asook die eerste reël van van die tweede aanstuur se teks, wat gewoonlik die "regte" teiken-bladsy gee waarna die eerste aanstuur behoort te wys.
'listgrouprights-addgroup-self-all' => 'Alle groepe byvoeg tot eie gebruiker',
'listgrouprights-removegroup-self-all' => 'Alle groepe verwyder van eie gebruiker',
-# E-mail user
+# Email user
'mailnologin' => 'Geen versendadres beskikbaar',
'mailnologintext' => "U moet [[Special:UserLogin|ingeteken]] wees en 'n geldige e-posadres in die [[Special:Preferences|voorkeure]] hê om e-pos aan ander gebruikers te stuur.",
'emailuser' => 'Stuur e-pos na hierdie gebruiker',
'usermessage-editor' => 'Stelselboodskapper',
# Watchlist
-'watchlist' => 'My dophoulys',
+'watchlist' => 'Dophoulys',
'mywatchlist' => 'Dophoulys',
'watchlistfor2' => 'Vir $1 $2',
'nowatchlist' => 'U het geen items in u dophoulys nie.',
'pageinfo-robot-noindex' => 'Nie indekseerbaar nie',
'pageinfo-views' => 'Aantal kere gewys',
'pageinfo-watchers' => 'Aantal dophouers',
+'pageinfo-few-watchers' => 'Minder as {{PLURAL:$1|dophouer|$1 dophouers}}',
'pageinfo-redirects-name' => 'Aansture na die bladsy',
'pageinfo-subpages-name' => 'Subblaaie van die bladsy',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|aanstuur|aansture}}; $3 {{PLURAL:$3|nie-aanstuur|nie-aansture}})',
'monthsall' => 'alle',
'limitall' => 'alle',
-# E-mail address confirmation
+# Email address confirmation
'confirmemail' => 'Bevestig e-posadres',
'confirmemail_noemail' => "U het nie 'n geldige e-posadres in u [[Special:Preferences|gebruikersvoorkeure]] gestel nie.",
'confirmemail_text' => "Hierdie wiki vereis dat u e-posadres bevestig word voordat epos-funksies gebruik word. Klik onderstaande knoppie om 'n bevestigingspos na u adres te stuur. Die pos sal 'n skakel met 'n kode insluit; maak hierdie skakel oop in u webblaaier om te bevestig dat die adres geldig is.",
'specialpages-group-highuse' => 'Baie gebruikte bladsye',
'specialpages-group-pages' => 'Lyste van bladsye',
'specialpages-group-pagetools' => 'Bladsyhulpmiddels',
-'specialpages-group-wiki' => 'Wiki data en hulpmiddels',
+'specialpages-group-wiki' => 'Data en hulpmiddels',
'specialpages-group-redirects' => 'Aanstuur gewone bladsye',
'specialpages-group-spam' => 'Spam-hulpmiddels',
'logentry-newusers-newusers' => 'Gebruiker $1 is geskep',
'logentry-newusers-create' => 'Gebruiker $1 is geskep',
'logentry-newusers-create2' => 'Gebruiker $3 is deur $1 geskep',
+'logentry-newusers-byemail' => 'Gebruiker $3 is deur $1 geskep en die wagwoord is per e-pos aangestuur',
'logentry-newusers-autocreate' => 'Die gebruiker $1 is outomaties geskep',
'logentry-rights-rights' => '$1 het groepslidmaatskap vir $3 van $4 na $5 gewysig',
'logentry-rights-rights-legacy' => '$1 het groepslidmaatskap vir $3 gewysig',
'api-error-ok-but-empty' => 'Interne fout: geen reaksie van die bediener.',
'api-error-overwrite' => "'N bestaande lêer vervang word nie toegelaat nie.",
'api-error-stashfailed' => 'Interne fout: Server nie tydelike lêer te stoor.',
+'api-error-publishfailed' => 'Interne fout: bediener kon nie die tydelike lêer publiseer nie.',
'api-error-timeout' => 'Die bediener het nie reageer binne die verwagte tyd.',
'api-error-unclassified' => "'n Onbekende fout het voorgekom.",
'api-error-unknown-code' => 'Onbekende fout: "$1"',
'duration-centuries' => '$1 {{PLURAL:$1|eeu|eeue}}',
'duration-millennia' => '$1 {{PLURAL:$1|millennium|millennia}}',
+# Unknown messages
+'pageswithprop-legend' => "Blaaie met 'n bladsy-eienskap",
+'pageswithprop-submit' => 'OK',
);
'pageinfo-lasttime' => 'ܣܝܩܘܡܐ ܕܫܘܚܠܦܐ ܐܚܪܝܐ',
'pageinfo-edits' => 'ܡܢܝܢܐ ܕܫܘܚܠܦ̈ܐ',
'pageinfo-authors' => 'ܡܢܝܢܐ ܕܡܫܚܠܦܢ̈ܐ ܡܫܚܠܦ̈ܐ',
-'pageinfo-recent-edits' => 'ܡܢܝܢܐ ܕܫܘܚܠܦ̈ܐ ܐܚܪ̈ܝܐ (ܒ {{PLURAL:$1||ܚܕ ܝܘܡܐ|$1 ܝܘܡܬ̈ܐ}})',
+'pageinfo-recent-edits' => 'ܡܢܝܢܐ ܕܫܘܚܠܦ̈ܐ ܐܚܪ̈ܝܐ (ܒ $1 ܕܕܥܒܪ)',
'pageinfo-recent-authors' => 'ܡܢܝܢܐ ܕܡܫܚܠܦܢ̈ܐ ܡܫܚܠܦ̈ܐ ܐܚܪ̈ܝܐ',
'pageinfo-toolboxlink' => 'ܝܕ̈ܥܬܐ ܥܠ ܦܐܬܐ',
'pageinfo-contentpage-yes' => 'ܐܝܢ',
'loginlanguagelabel' => 'Мова: $1',
'suspicious-userlogout' => 'Ваш запыт на выхад быў адмоўлены, паколькі ён выглядае як накіраваны са зламанага браўзера або кэшаванне проксі-сервераў.',
-# E-mail sending
+# Email sending
'php-mail-error-unknown' => 'Невядомая памылка ў функцыі PHP-пошты',
'user-mail-no-addy' => 'Паспрабаваў адправіць электронны ліст без адрасу электроннай пошты',
'prefs-displaywatchlist' => 'Паказ',
'prefs-diffs' => 'Розніцы',
-# User preference: e-mail validation using jQuery
+# User preference: email validation using jQuery
'email-address-validity-valid' => "Адрас электроннай пошты з'яўляецца сапраўдным",
'email-address-validity-invalid' => 'Увядзіце слушны адрас электроннай пошты',
'action-sendemail' => 'адпраўка электронных пісем',
# Recent changes
-'nchanges' => '$1 {{PLURAL:$1|мена|менаў}}',
+'nchanges' => '$1 {{PLURAL:$1|змена|зменÑ\8b|зменаў}}',
'recentchanges' => 'Нядаўнія змяненні',
'recentchanges-legend' => 'Магчымасці паказу',
'recentchanges-summary' => 'Гэта апошнія мены на пляцоўцы {{SITENAME}}.',
'listgrouprights-addgroup-self-all' => 'Дадаць усе групы да свайго акаунта',
'listgrouprights-removegroup-self-all' => 'Выдаліць усе групы са свайго акаунта',
-# E-mail user
+# Email user
'mailnologin' => 'Няма эл.адрасу',
'mailnologintext' => 'Трэба [[Special:UserLogin|ўвайсці ў сістэму]] і мець пацверджаны адрас эл.пошты ў сваіх [[Special:Preferences|настáўленнях]], каб слаць эл.пошту іншым удзельнікам.',
'emailuser' => 'Эл.пошта ўдзельніка',
'contributions-title' => 'Уклад удзельніка $1',
'mycontris' => 'Уклад',
'contribsub2' => 'Для $1 ($2)',
-'nocontribs' => 'Не знойдзена менаў, адпаведных зададзеным параметрам.',
+'nocontribs' => 'Ð\9dе знойдзена зменаÑ\9e, адпаведнÑ\8bÑ\85 зададзенÑ\8bм паÑ\80амеÑ\82Ñ\80ам.',
'uctop' => '(апошн.)',
'month' => 'Ад месяцу (і раней):',
'year' => 'Ад году (і раней):',
'monthsall' => 'усе',
'limitall' => 'усе',
-# E-mail address confirmation
+# Email address confirmation
'confirmemail' => 'Пацвердзіць адрас эл.пошты',
'confirmemail_noemail' => 'У [[Special:Preferences|вашых настаўленнях]] няма дапушчальнага адрасу эл.пошты.',
'confirmemail_text' => 'На пляцоўцы {{SITENAME}} патрабуецца праверка адрасу эл.пошты перад тым, як карыстацца магчымасцямі эл.пошты. Націсніце кнопку, што ніжэй, каб адаслаць сабе пацвярджальны ліст. У лісце будзе спасылка на спецыяльную пацвярджальную старонку, якую трэба будзе адкрыць у браўзеры, каб пацвердзіць правільнасць свайго адрасу эл.пошты.',
'tags-description-header' => 'Поўнае апісанне значэння',
'tags-hitcount-header' => 'Пазначаных правак',
'tags-edit' => 'правіць',
-'tags-hitcount' => '$1 {{PLURAL:$1|мена|менаў}}',
+'tags-hitcount' => '$1 {{PLURAL:$1|змена|зменÑ\8b|зменаў}}',
# Special:ComparePages
'comparepages' => 'Параўнанне старонак',
'editundo' => 'връщане',
'diff-multi' => '({{PLURAL:$1|Не е показана една междинна версия|Не са показани $1 междинни версии}} от {{PLURAL:$2|един потребител|$2 потребителя}}.)',
'diff-multi-manyusers' => '({{PLURAL:$1|Не е показана една междинна версия|Не са показани $1 междинни версии}} от повече от $2 {{PLURAL:$2|потребител|потребителя}})',
+'difference-missing-revision' => '{{PLURAL:$2|Не беше открита|Не бяха открити}} {{PLURAL:$2|една версия|$2 версии}} от тази разликова препратка ($1).
+
+Това обикновено се случва, когато е последвана остаряларазликова препратка на страница,коятоебила изтрита.
+Повече подробности могат да бъдат открити в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневника на изтриванията].',
# Search results
'searchresults' => 'Резултати от търсенето',
'search-interwiki-default' => '$1 резултата:',
'search-interwiki-more' => '(още)',
'search-relatedarticle' => 'Свързани',
-'mwsuggest-disable' => 'Изключване на AJAX предположенията',
+'mwsuggest-disable' => 'Изключване на предположенията при търсене',
'searcheverything-enable' => 'Търсене във всички именни пространства',
'searchrelated' => 'свързани',
'searchall' => 'всички',
'mailnologintext' => 'Необходимо е да [[Special:UserLogin|влезете]] и да посочите валидна електронна поща в [[Special:Preferences|настройките]] си, за да може да пращате писма на други потребители.',
'emailuser' => 'Писмо до потребителя',
'emailpage' => 'Пращане писмо на потребител',
-'emailpagetext' => 'Можете да използвате формуляра по-долу, за да изпратите електронно писмо на този потребител.
-Адресът, който се въвели в [[Special:Preferences|настройките си]], ще се появи в полето „От“ на писмото, така че получателят ще е в състояние да ви отговори.',
+'emailpagetext' => 'Можете да използвате формуляра по-долу, за да изпратите електронно писмо на {{GENDER:$1|този потребител}}.
+Адресът, който се въвели в [[Special:Preferences|настройките си]], ще се появи в полето „От“ на писмото, така че получателят ще е в състояние да ви отговори директно.',
'usermailererror' => 'Пощенският обект даде грешка:',
'defemailsubject' => 'Писмо от потребител $1 в {{SITENAME}}',
'usermaildisabled' => 'Потребителят не е разрешил да получава електронна поща',
'pageinfo-lasttime' => 'Дата на последнoто редактиране',
'pageinfo-edits' => 'Общ брой редакции',
'pageinfo-authors' => 'Общ брой на отделните автори',
+'pageinfo-recent-edits' => 'Скорошен брой редакции (в рамките на $1)',
'pageinfo-magic-words' => '{{PLURAL:$1|Вълшебна думичка|Вълшебни думички}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Скрита категория|Скрити категории}} ($1)',
'pageinfo-toolboxlink' => 'Информация за страницата',
'file-info-size-pages' => '$1 × $2 пиксела, размер на файла: $3, MIME тип: $4, $5 {{PLURAL:$5|страница|страници}}',
'file-nohires' => 'Не е налична версия с по-висока разделителна способност.',
'svg-long-desc' => 'Файл във формат SVG, основен размер: $1 × $2 пиксела, големина на файла: $3',
+'svg-long-desc-animated' => 'Анимиран SVG файл, основен размер $1 × $2 пиксела, големина на файла: $3',
'svg-long-error' => 'Невалиден SVG файл: $1',
'show-big-image' => 'Пълна разделителна способност',
'show-big-image-preview' => 'Размер на този преглед: $1.',
'version-license' => 'Лиценз',
'version-poweredby-credits' => "Това уики се задвиждва от '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
'version-poweredby-others' => 'други',
+'version-credits-summary' => 'Бихме искали да изкажем признателност на следните хора за техните приноси към [[Special:Version|MediaWiki]].',
'version-license-info' => 'MediaWiki е свободен софтуер, можете да го разпространявате и/или променяте съгласно условията на GNU General Public License, както е публикуван от Free Software Foundation, версия 2 на лиценза или (по ваше усмотрение) която и да е следваща версия.
MediaWiki се разпространява с надеждата, че ще бъде полезен, но БЕЗ НИКАКВИ ГАРАНЦИИ, без дори косвена гаранция за ПРОДАВАЕМОСТ или ПРИГОДНОСТ ЗА КОНКРЕТНА УПОТРЕБА. Вижте GNU General Public License за повече подробности.
'Userlogin' => array( 'Anmelden' ),
'Userlogout' => array( 'Abmelden' ),
'Userrights' => array( 'Benutzerrechte' ),
- 'Version' => array( 'Versionsinformationen' ),
'Wantedcategories' => array( 'Gewünschte_Kategorien' ),
'Wantedfiles' => array( 'Gewünschte_Dateien', 'Fehlende_Dateien' ),
'Wantedpages' => array( 'Gewünschte_Seiten' ),
'viewsourcetext' => 'To şikinay çımey na pele bıvêne u kopya kerê:',
'viewyourtext' => "Na pela '''Vurnayışê ke kerdê''' re şıma şenê kopya kerê:",
'protectedinterface' => 'Na pela qandê nusnerin destegê verri dana u kes xırabin nêqero deye kerda kılit.',
-'editinginterface' => "'''İqaz:''' Şıma hao jû pela ke seba nuşteyê meqalanê cayanê bırnayeyan dana, vurnenê.
+'editinginterface' => "'''İqaz:''' Şıma hayo yew pela ke seba nuşteyê meqalanê cayanê bırnayeyan dana, vurnenê.
Vurnayışê na pele karberanê binan rê serpela karberi kena ke bımocno.
Seba çarnayışi, yardımê [//translatewiki.net/wiki/Main_Page?setlang=diq translatewiki.net]i ra procêdoşkerdışi rê diqet kerên.",
'sqlhidden' => '(SQL pers kerdışê nımıte)',
'searchsubtitle' => 'Tı semedê \'\'\'[[:$1]]\'\'\' cıgeyra. ([[Special:Prefixindex/$1|pelê ke pêro be "$1" ra dest niyaê pıra]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|pelê ke pêro be "$1"\' ra gırê xo esto]])',
'searchsubtitleinvalid' => "Tı cıgeyra qe '''$1'''",
'toomanymatches' => 'Zêde teki (zewci) peyser çarnay, şıma rê zehmet, be persê do bin ra bıcerrebnên.',
-'titlematches' => 'tekê (zewcê) sernamey pele',
-'notitlematches' => 'Tekê (zewcê) sernamey pele çıniyê.',
+'titlematches' => 'Tekê (zewcê) sernameyê pele',
+'notitlematches' => 'Tekê (zewcê) sernameyê pele çıniyê.',
'textmatches' => 'Tekê (zewcê) nuştey pele',
'notextmatches' => 'tekê (zewcê) nuştey pele çıniyê',
'prevn' => '{{PLURAL:$1|$1}} verên',
'filedelete-success-old' => "Versiyonê'''[[Media:$1|$1]]'''î $3, $2 esteriyayo.",
'filedelete-nofile' => "'''$1''' çin o.",
'filedelete-nofile-old' => "Versiyonê arşivi ye '''$1'''î pê enê detayanê xasî çin o.",
-'filedelete-otherreason' => 'Sebebê binî',
-'filedelete-reason-otherlist' => 'Sebebê binî',
+'filedelete-otherreason' => 'Sebebo bin/ilaweyın:',
+'filedelete-reason-otherlist' => 'Sebebo bin',
'filedelete-reason-dropdown' => '*sebebê hewna kerdışi
** ihlalê heqê telifi
** Çift/dosyaya kopyayın',
-'filedelete-edit-reasonlist' => 'Sebebê esterayîşî bivurne',
+'filedelete-edit-reasonlist' => 'Sebebanê esterıtışi bıvurne',
'filedelete-maintenance' => 'Esterayîş u resterasyonê dosyayî wextê texmirî de nibenê.',
'filedelete-maintenance-title' => 'Dosyaya nêbesterneyêna',
'sp-contributions-blocked-notice-anon' => 'Eno adresê IPi bloke biyo.
Cıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:',
'sp-contributions-search' => 'Dekerdena cı geyrê',
-'sp-contributions-username' => 'Adresa IP yana namey karberi:',
+'sp-contributions-username' => 'Adresa IPy ya zi nameyê karberi:',
'sp-contributions-toponly' => 'Tenya rewizyonanê tewr peyniyan bimocne',
'sp-contributions-submit' => 'Cı geyre',
'blockip-title' => 'Karberi kılit ke',
'blockip-legend' => 'Karber blok bike',
'blockiptext' => 'pê şuxulnayişê formê cêrıni, şıma eşkeni verniyê vurnayişkerdışê yew karberi ya zi yew IPyi bıgêrî. No têna qey verni-gırewtışê vandalizmiyo u gani şıma [[{{MediaWiki:Policy-url}}|qaydeyan]] re diqqet bıkeri. cêr de muheqqeq sebebê verni-grewtışi bınusi. (mesela: -nê- pelani de vandalizm kerdo).',
-'ipadressorusername' => 'Adresa IP yana namey karberi:',
+'ipadressorusername' => 'Adresa IPy ya zi nameyê karberi:',
'ipbexpiry' => 'Qedyayış:',
'ipbreason' => 'Sebeb:',
'ipbreasonotherlist' => 'Sebebê bini',
'ipb-blocklist' => 'Blokî ke hama estê ey bivîne',
'ipb-blocklist-contribs' => 'Ser $1 îştîrakî',
'unblockip' => 'Hesabê karberî a bike',
-'unblockiptext' => 'eke şıma qayili ê yê ke verniyê IPadesê inan geriyayê akeri formê cêrıni dekerê.',
-'ipusubmit' => 'Ena blok wedarne',
+'unblockiptext' => 'Cıreştışê nuştışê IP ya zi karberio ke ver ra gêriyayo, seba peyser barkerdışi dey rê formê cêrêni bıgurenên.',
+'ipusubmit' => 'Enê kılitkerdışi wedare',
'unblocked' => '[[User:$1|$1]] blok biyo',
'unblocked-range' => "Blokey $1'i wederya",
'unblocked-id' => 'Blokê $1î wedariyayo',
-'blocklist' => 'Karberê kılitbiyaey',
-'ipblocklist' => 'Karberê kılitbiyaey',
-'ipblocklist-legend' => 'Yew karberê blok biyaye bivîne',
-'blocklist-userblocks' => 'Wederneyanê hesaba bınımne',
-'blocklist-tempblocks' => 'Wederneyanê idaretan bınımne',
-'blocklist-addressblocks' => 'Nêverdışanê IP bınımne',
-'blocklist-rangeblocks' => 'Nêverdışanê gırda bınımne',
+'blocklist' => 'Karberê kılitbiyayey',
+'ipblocklist' => 'Karberê kılitbiyayey',
+'ipblocklist-legend' => 'Yew karberê kılitbiyayey bıvêne',
+'blocklist-userblocks' => 'Kılitkerdışê hesaban bınımne',
+'blocklist-tempblocks' => 'Kılitkerdışan mıweqet bınımne',
+'blocklist-addressblocks' => 'Tenya kılitkerdışanê IPy bınımne',
+'blocklist-rangeblocks' => 'Kılitkerdışanê rêzkiyan bınımne',
'blocklist-timestamp' => 'İmzay demi',
'blocklist-target' => 'Menzil',
'blocklist-expiry' => 'Wahdey qedyayışi',
'createaccountblock' => 'Hesab viraştîş blok biyo',
'emailblock' => 'e-mail blok biyo',
'blocklist-nousertalk' => 'ti nieşken pele minaqaşe xo bivurne',
-'ipblocklist-empty' => 'Listeyê blokî veng o.',
+'ipblocklist-empty' => 'Lista kılitkerdışi venga.',
'ipblocklist-no-results' => 'Adresa IPya waştiye ya zi namey karberi kılit nêbiyo.',
'blocklink' => 'kılit ke',
'unblocklink' => 'bloqi hewad',
*/
/**
- * Fallback language, used for all unspecified messages and behaviour. This
+ * Fallback language, used for all unspecified messages and behavior. This
* is English by default, for all files other than this one.
*
* Do NOT set this to false in any other message file! Leave the line out to
/**
* Magic words
- * Customisable syntax for wikitext and elsewhere.
+ * Customizable syntax for wikitext and elsewhere.
*
* IDs must be valid identifiers, they cannot contain hyphens.
* CASE is 0 to match all case variants, 1 for case-sensitive
/*
The sidebar for MonoBook is generated from this message, lines that do not
begin with * or ** are discarded, furthermore lines that do begin with ** and
-do not contain | are also discarded, but do not depend on this behaviour for
+do not contain | are also discarded, but do not depend on this behavior for
future releases. Also note that since each list value is wrapped in a unique
XHTML id it should only appear once and include characters that are legal
XHTML id names.
** Removing content from pages
** Spamming links to external sites
** Inserting nonsense/gibberish into pages
-** Intimidating behaviour/harassment
+** Intimidating behavior/harassment
** Abusing multiple accounts
** Unacceptable username',
'ipb-hardblock' => 'Prevent logged-in users from editing from this IP address',
'unblockip' => 'Unblock user',
'unblockiptext' => 'Use the form below to restore write access to a previously blocked IP address or username.',
'ipusubmit' => 'Remove this block',
-'unblocked' => '[[User:$1|$1]] has been unblocked',
-'unblocked-range' => '$1 has been unblocked',
-'unblocked-id' => 'Block $1 has been removed',
+'unblocked' => '[[User:$1|$1]] has been unblocked.',
+'unblocked-range' => '$1 has been unblocked.',
+'unblocked-id' => 'Block $1 has been removed.',
'blocklist' => 'Blocked users',
'ipblocklist' => 'Blocked users',
'ipblocklist-legend' => 'Find a blocked user',
Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
'allmessagesnotsupportedDB' => "This page cannot be used because '''\$wgUseDatabaseMessages''' has been disabled.",
'allmessages-filter-legend' => 'Filter',
-'allmessages-filter' => 'Filter by customisation state:',
+'allmessages-filter' => 'Filter by customization state:',
'allmessages-filter-unmodified' => 'Unmodified',
'allmessages-filter-all' => 'All',
'allmessages-filter-modified' => 'Modified',
'duration-centuries' => '$1 {{PLURAL:$1|century|centuries}}',
'duration-millennia' => '$1 {{PLURAL:$1|millennium|millennia}}',
+#Rotation
+'rotate-comment' => 'Image rotated by $1 {{PLURAL:$1|degree|degrees}} clockwise',
+
);
'nonunicodebrowser' => "'''OHARRA: Zure nabigatzailea ez dator Unicode arauarekin bat. Artikuluak modu seguruan aldatu ahal izateko beste sistema bat gaitu da: ASCII ez diren karaktereak kode hamaseitar bezala agertuko dira aldaketa koadroan.'''",
'editingold' => "'''KONTUZ: Artikulu honen bertsio zahar bat aldatzen ari zara. Gorde egiten baduzu, azkenengo aldaketa baino lehenagoko aldakuntzak, ezabatuak izango dira.'''",
'yourdiff' => 'Ezberdintasunak',
-'copyrightwarning' => "Kontuan izan {{SITENAME}}(e)n egindako ekarpen guztiak $2 baldintzapean argitaratzen direla (ikus $1 informazio gehiagorako). Zure testua banatzeko baldintza hauekin ados ez bazaude, ez ezazu bidali.<br />
-Era berean, bidaltzen ari zaren edukia zuk zeuk idatzitakoa dela edo jabetza publikoko edo baliabide aske batetik kopiatu duzula zin egin ari zara.
-'''EZ BIDALI BAIMENIK GABEKO COPYRIGHTDUN EDUKIRIK!'''",
-'copyrightwarning2' => "Mesedez, kontuan izan {{SITENAME}}(e)n egindako ekarpen guztiak besteek aldatu edo ezabatu ditzaketela. Ez baduzu besteek aldaketak egitea nahi, ez ezazu bidali.<br />
-Era berean, bidaltzen ari zaren edukia zuk zeuk idatzitakoa dela edo jabetza publikoko edo baliabide aske batetik kopiatu duzula zin egin ari zara (ikus $1 informazio gehiagorako).
-'''EZ BIDALI BAIMENIK GABEKO COPYRIGHTDUN EDUKIRIK!'''",
+'copyrightwarning' => "Kontuan izan ezazu {{SITENAME}} webgunean egindako ekarpen guztiak $2 lizentziaren pean argitaratzen direla (xehetasunetarako, ikus $1). Zuk idatzitakoa libreki aldatua eta banatua izatea nahi ez baduzu, ez ezazu hemen jarri.<br />
+Era berean, hitzematen ari zara hau zuk zeuk idatzia dela, edo jabari publikotik nahiz askea den beste ituri batetik kopiatu duzula.
+'''Ez erabili copyright eskubideek babestutako lanik, baimenik gabe!'''",
+'copyrightwarning2' => "Mesedez, kontuan izan ezazu {{SITENAME}} webgunean egindako ekarpen guztiak beste erabiltzaileek aldatu edo ezabatu ditzaketela. Zuk idatzitakoa libreki aldatua izatea nahi ez baduzu, ez ezazu hemen jarri.<br />
+Era berean, hitzematen ari zara hau zuk zeuk idatzia dela, edo jabari publikotik nahiz askea den beste ituri batetik kopiatu duzula (xehetasunetarako, ikus $1).
+'''Ez erabili copyright eskubideek babestutako lanik, baimenik gabe!'''",
'longpageerror' => "'''Errorea: Bidali duzun testuak {{PLURAL:$1|kilobyte 1eko|$1 kilobyteko}} luzera du, eta {{PLURAL:$2|kilobyte 1eko|$2 kilobyteko}} maximoa baino luzeagoa da.'''
Ezin da gorde.",
'readonlywarning' => "'''Oharra: Datu-basea blokeatu egin da mantenu lanak burutzeko, beraz ezingo dituzu orain zure aldaketak gorde.'''
Mesedez beheko alderaketa egiaztatu, egin nahi duzuna hori dela frogatzeko, eta ondoren azpiko aldaketak gorde, aldaketa desegiten amaitzeko.',
'undo-failure' => 'Ezin izan da aldaketa desegin tarteko aldaketekin gatazkak direla-eta.',
'undo-norev' => 'Aldaketa ezin da desegin ez delako existitzen edo ezabatu zutelako.',
-'undo-summary' => '[[Special:Contributions/$2|$2(r)en]] $1 berrikuspena desegin da ([[User talk:$2|Eztabaida]])',
+'undo-summary' => '[[Special:Contributions/$2|$2]] ([[User talk:$2|eztabaida]]) wikilariaren $1 berrikuspena desegin da',
# Account creation failure
'cantcreateaccounttitle' => 'Ezin izan da kontua sortu',
این صفحهها شاید در عوض به موضوعات مرتبط پیوند داده شوند.<br />
یک صفحه هنگامی صفحهٔ ابهامزدایی در نظر گرفته میشود که در آن از الگویی که به [[MediaWiki:Disambiguationspage]] پیوند دارد استفاده شده باشد.",
+'pageswithprop' => 'صفحههای دارای خاصیت صفحه',
+'pageswithprop-text' => 'این صفحه فهرستی است از صفحههایی که از یک خاصیت صفحهٔ خاص استفاده میکنند.',
+'pageswithprop-prop' => 'نام خاصیت:',
+
'doubleredirects' => 'تغییرمسیرهای دوتایی',
'doubleredirectstext' => 'این صفحه فهرستی از صفحههای تغییرمسیری را ارائه میکند که به صفحهٔ تغییرمسیر دیگری اشاره میکنند.
هر سطر دربردارندهٔ پیوندهایی به تغییرمسیر اول و دوم و همچنین مقصد تغییرمسیر دوم است، که معمولاً صفحهٔ مقصد واقعی است و نخستین تغییرمسیر باید به آن اشاره کند.
'duration-centuries' => '$1 قرن',
'duration-millennia' => '{{PLURAL:$1|هزار سال |$1 هزار سال}}',
+# Unknown messages
+'pageswithprop-legend' => 'صفحههای دارای خاصیت صفحه',
+'pageswithprop-submit' => 'برو',
);
Täsmennyssivun sijaan ne voisivat linkittää suoraan asianomaiseen aiheeseen.<br />
Sivua kohdellaan täsmennyssivuna, jos se käyttää mallinetta, johon on linkki sivulta [[MediaWiki:Disambiguationspage]].",
+'pageswithprop' => 'Sivut sivun ominaisuuden mukaan',
+'pageswithprop-text' => 'Tällä sivulla on lueteltu sivut, jotka käyttävät erityistä sivun ominaisuutta.',
+
'doubleredirects' => 'Kaksinkertaiset ohjaukset',
'doubleredirectstext' => 'Tässä listassa on ohjaussivut, jotka ohjaavat toiseen ohjaussivuun.
Jokaisella rivillä on linkit ensimmäiseen ja toiseen ohjaukseen sekä toisen ohjauksen kohteen ensimmäiseen riviin, eli yleensä ”oikeaan” kohteeseen, johon ensimmäisen ohjauksen pitäisi osoittaa.
'duration-millennia' => '$1 {{PLURAL:$1|vuosituhat|vuosituhatta}}',
# Unknown messages
+'pageswithprop-legend' => 'Sivut sivun ominaisuuden mukaan',
'pageswithprop-submit' => 'Siirry',
);
'loginlanguagelabel' => 'Spräke: $1',
'suspicious-userlogout' => 'Dan Oufmäldönjfrååge wörd ferwaigred, deer ja fermouslik foon en defäkte browser unti en cache-proxy sånd wörd.',
-# E-mail sending
+# Email sending
'php-mail-error-unknown' => 'Ünbekäänd feeler mä det funktsjuun mail() faan PHP.',
'user-mail-no-addy' => 'Köö niinj e-mail schake suner e-mail-adres.',
'user-mail-no-body' => 'Dü wulst en e-mail saner tekst wechsjüür.',
'search-interwiki-default' => '$1 resultoote:',
'search-interwiki-more' => '(widere)',
'search-relatedarticle' => 'früne',
-'mwsuggest-disable' => 'forsliike per Ajax deaktiviire',
+'mwsuggest-disable' => "Föörslacher för't sjüken deaktiwiare",
'searcheverything-enable' => 'Onj ål noomerüme säke',
'searchrelated' => 'früne',
'searchall' => 'åle',
'prefs-displaywatchlist' => "Mögelkhaiden för't uunwisin",
'prefs-diffs' => 'Ferskeel',
-# User preference: e-mail validation using jQuery
+# User preference: email validation using jQuery
'email-address-validity-valid' => 'Detdiar E-Mail-adres schocht gud ütj.',
'email-address-validity-invalid' => 'Du en echt E-Mail-adres uun.',
# Special:ListGroupRights
'listgrouprights-members' => '(lasmoote-list)',
-# E-mail user
+# Email user
'emailuser' => 'E-mail tu dideere brüker',
# Watchlist
'listgrouprights-helppage' => 'Help:Kiartyn y phossan',
'listgrouprights-members' => '(rolley olteynyn)',
-# E-mail user
+# Email user
'emailuser' => "Cur post-L da'n ymmydeyr shoh",
'emailfrom' => 'Veih:',
'emailto' => 'Da:',
** Removing content from pages
** Spamming links to external sites
** Inserting nonsense/gibberish into pages
-** Intimidating behaviour/harassment
+** Intimidating behavior/harassment
** Abusing multiple accounts
* Oyr elley
** Ennym ymmydeyryn neuchooie
'''הוא טרם נשמר!'''",
'sitejspreview' => "'''זכרו שזו רק תצוגה מקדימה של קוד ה־JavaScript הזה.'''
'''הוא טרם נשמר!'''",
-'userinvalidcssjstitle' => "'''אזהרה''': העיצוב \"\$1\" אינו קיים.
+'userinvalidcssjstitle' => "'''אזהרה:''' העיצוב \"\$1\" אינו קיים.
דפי .css ו־.js מותאמים אישית משתמשים בכותרת עם אותיות קטנות – למשל, {{ns:user}}:דוגמה/vector.css ולא {{ns:user}}:דוגמה/Vector.css.",
'updated' => '(מעודכן)',
'note' => "'''הערה:'''",
'showingresults' => "{{PLURAL:$1|מוצגת תוצאה '''אחת'''|מוצגות עד '''$1''' תוצאות}} החל ממספר '''$2''':",
'showingresultsnum' => "{{PLURAL:$3|מוצגת תוצאה '''אחת'''|מוצגות '''$3''' תוצאות}} החל ממספר '''$2''':",
'showingresultsheader' => "{{PLURAL:$5|תוצאה '''$1''' מתוך '''$3'''|תוצאות '''$1 - $2''' מתוך '''$3'''}} עבור '''$4'''",
-'nonefound' => "'''הערה''': כברירת מחדל, החיפוש מבוצע במספר מרחבי שם בלבד. באפשרותכם לכתוב '''all:''' לפני מונח החיפוש כדי לחפש בכל הדפים (כולל דפי שיחה, תבניות, ועוד), או לכתוב לפני מונח החיפוש את מרחב השם שאתם מעוניינים בו.",
+'nonefound' => "'''הערה:''' כברירת מחדל, החיפוש מבוצע במספר מרחבי שם בלבד. באפשרותכם לכתוב '''all:''' לפני מונח החיפוש כדי לחפש בכל הדפים (כולל דפי שיחה, תבניות, ועוד), או לכתוב לפני מונח החיפוש את מרחב השם שאתם מעוניינים בו.",
'search-nonefound' => 'לא נמצאו תוצאות המתאימות לחיפוש.',
'powersearch' => 'חיפוש מתקדם',
'powersearch-legend' => 'חיפוש מתקדם',
דף נחשב לדף פירושונים אם הוא משתמש בתבנית המקושרת מהדף [[MediaWiki:Disambiguationspage]].",
'pageswithprop' => 'דפים עם מאפיין דף',
-'pageswithprop-text' => '×\94×\93×£ ×\94×\96×\94 × ×\95ת×\9f רש×\99×\9e×\94 ש×\9c דפים שמשתמשים במאפיין דף מסוים.',
+'pageswithprop-text' => '×\91×\93×£ ×\96×\94 ×\9e×\95פ×\99×¢×\94 רש×\99×\9eת דפים שמשתמשים במאפיין דף מסוים.',
'pageswithprop-prop' => 'שם המאפיין:',
'doubleredirects' => 'הפניות כפולות',
'unblockiptext' => 'השתמשו בטופס שלהלן כדי להחזיר את הרשאות הכתיבה למשתמש או כתובת IP חסומים.',
'ipusubmit' => 'שחרור חסימה',
'unblocked' => 'המשתמש [[User:$1|$1]] שוחרר מחסימתו.',
-'unblocked-range' => '$1 שוחרר מחסימתו',
+'unblocked-range' => '$1 שוחרר מחסימתו.',
'unblocked-id' => 'חסימה מספר $1 שוחררה.',
'blocklist' => 'משתמשים חסומים',
'ipblocklist' => 'משתמשים חסומים',
'scarytranscludetoolong' => '[כתובת ה־URL ארוכה מדי]',
# Delete conflict
-'deletedwhileediting' => "'''אזהרה''': דף זה נמחק לאחר שהתחלתם לערוך!",
+'deletedwhileediting' => "'''אזהרה:''' דף זה נמחק לאחר שהתחלתם לערוך!",
'confirmrecreate' => "הדף נמחק על ידי המשתמש [[User:$1|$1]] ([[User talk:$1|שיחה]]) לאחר שהתחלתם לערוך אותו, מסיבה זו:
:'''$2'''
אנא אשרו שאתם אכן רוצים ליצור מחדש את הדף.",
# Unknown messages
'pageswithprop-legend' => 'דפים עם מאפיין דף',
-'pageswithprop-submit' => 'ש×\9c×\99×\97ה',
+'pageswithprop-submit' => '×\94צ×\92ה',
);
'loginlanguagelabel' => 'Jezik: $1',
'suspicious-userlogout' => 'Vaš zahtjev za odjavu je odbijen jer to izgleda kao da je poslan preko pokvarenog preglednika ili keširanog posrednika (proxyja).',
-# E-mail sending
+# Email sending
'php-mail-error-unknown' => 'Nepoznata pogreška u PHP-mail() funkciji',
'user-mail-no-addy' => 'Pokušaj slanja e-maila bez e-mail adrese.',
'prefs-displaywatchlist' => 'Opcije prikaza',
'prefs-diffs' => 'razl',
-# User preference: e-mail validation using jQuery
-'email-address-validity-valid' => 'E-mail adresa se pokazuje ispravnom',
-'email-address-validity-invalid' => 'Unesite valjanu e-mail adresu',
+# User preference: email validation using jQuery
+'email-address-validity-valid' => 'Adresa e-pošte pokazuje se ispravnom',
+'email-address-validity-invalid' => 'Unesite valjanu adresu e-pošte',
# User rights
'userrights' => 'Upravljanje suradničkim pravima',
'listgrouprights-addgroup-self-all' => 'Dodaj sve skupine vlastitom računu',
'listgrouprights-removegroup-self-all' => 'Uklonite sve skupine iz vlastitog računa',
-# E-mail user
+# Email user
'mailnologin' => 'Nema adrese pošiljaoca',
'mailnologintext' => 'Morate biti [[Special:UserLogin|prijavljeni]]
i imati valjanu adresu e-pošte u svojim [[Special:Preferences|postavkama]]
'anononlyblock' => 'samo IP adrese',
'noautoblockblock' => 'blokiranje samoga sebe je onemogućeno',
'createaccountblock' => 'blokirano stvaranje suradničkog računa',
-'emailblock' => 'e-mail je blokiran',
+'emailblock' => 'e-pošta je blokirana',
'blocklist-nousertalk' => 'bez uređivanja vlastite stranice za razgovor',
'ipblocklist-empty' => 'Popis blokiranja je prazan.',
'ipblocklist-no-results' => 'Tražena IP adresa ili suradničko ime nije blokirano.',
'unblocklink' => 'deblokiraj',
'change-blocklink' => 'promijeni blokiranje',
'contribslink' => 'doprinosi',
-'emaillink' => 'pošalji e-mail',
+'emaillink' => 'pošalji e-poruku',
'autoblocker' => 'Automatski ste blokirani jer je Vašu IP adresu nedavno koristio "[[User:$1|$1]]" koji je blokiran zbog: "$2".',
'blocklogpage' => 'Evidencija blokiranja',
'blocklog-showlog' => 'Ovaj suradnik je ranije blokiran.
'monthsall' => 'sve',
'limitall' => 'sve',
-# E-mail address confirmation
+# Email address confirmation
'confirmemail' => 'Potvrda e-mail adrese',
'confirmemail_noemail' => 'Niste unijeli važeću e-mail adresu u Vaše [[Special:Preferences|suradničke postavke]].',
'confirmemail_text' => 'U ovom wikiju morate prije korištenja e-mail naredbi potvrditi svoju e-mail adresu. Kliknite na gumb ispod kako biste poslali poruku s potvrdom na Vašu adresu. U poruci će biti poveznica koju morate otvoriti u svom web pregledniku i time potvrditi svoju e-mail adresu.',
'skinname-myskin' => 'ԻմՏեսք',
'skinname-chick' => 'Ծիտ',
'skinname-simple' => 'Պարզ',
+'skinname-modern' => 'Մոդերն',
+'skinname-vector' => 'Սովորական',
# Patrolling
'markaspatrolleddiff' => 'Նշել որպես ստուգված',
'mediawarning' => "'''Զգուշացում'''. այս նիշքի տեսակը կարող է պարունակել վնասակար ծրագրային կոդ։ Այն կիրարկելը կարող է վտանգել ձեր համակարգը։",
'imagemaxsize' => 'Պատկերի էջում պատկերի չափի սահմանափակում.',
'thumbsize' => 'Պատկերների փոքրացված չափ.',
+'widthheight' => '$1 × $2',
'widthheightpage' => '$1 × $2, $3 էջեր',
'file-info' => 'նիշքի չափ՝ $1, MIME-տեսակ՝ $2',
'file-info-size' => '$1 × $2 փիքսել, նիշքի չափը՝ $3, MIME-տեսակը՝ $4',
'tog-previewonfirst' => 'Monstrar previsualisation al prime modification',
'tog-nocache' => "Disactivar le ''cache'' de paginas in le navigator",
'tog-enotifwatchlistpages' => 'Notificar me per e-mail quando un pagina o file in mi observatorio es modificate',
-'tog-enotifusertalkpages' => 'Notificar me via e-mail quando mi pagina de discussion es modificate',
+'tog-enotifusertalkpages' => 'Notificar me per e-mail quando mi pagina de discussion es modificate',
'tog-enotifminoredits' => 'Notificar me etiam de modificationes minor de paginas e files',
'tog-enotifrevealaddr' => 'Revelar mi adresse de e-mail in messages de notification',
'tog-shownumberswatching' => 'Monstrar le numero de usatores que observa le pagina',
'passwordsent' => 'Un nove contrasigno ha essite inviate al adresse de e-mail registrate pro "$1".
Per favor aperi session de novo post reciper lo.',
'blocked-mailpassword' => 'Tu adresse IP es blocate de facer modificationes, e pro impedir le abuso, le uso del function pro recuperar contrasignos es equalmente blocate.',
-'eauthentsent' => 'Un e-mail de confirmation ha essite inviate al adresse de e-mail nominate.
-Ante que alcun altere e-mail se invia al conto, tu debera sequer le instructiones in le e-mail, pro confirmar que le conto es de facto tue.',
+'eauthentsent' => 'Un e-mail de confirmation ha essite inviate al adresse de e-mail specificate.
+Pro poter reciper altere e-mail a iste conto, tu debe sequer le instructiones in iste e-mail pro confirmar que le conto es realmente tue.',
'throttled-mailpassword' => 'Un rememoration del contrasigno ha jam essite inviate intra le ultime {{PLURAL:$1|hora|$1 horas}}.
Pro prevenir le abuso, solmente un rememoration de contrasigno essera inviate per {{PLURAL:$1|hora|$1 horas}}.',
'mailerror' => 'Error de inviar e-mail: $1',
'acct_creation_throttle_hit' => 'Le visitatores de iste wiki usante tu adresse IP ha create {{PLURAL:$1|1 conto|$1 contos}} durante le ultime die, e isto es le maximo permittite in iste periodo de tempore.
A causa de isto, le visitatores usante iste adresse IP non pote crear nove contos al momento.',
-'emailauthenticated' => 'Tu adresse de e-mail esseva authentificate le $2 a $3.',
-'emailnotauthenticated' => 'Tu adresse de e-mail non ha essite authentificate ancora.
-Nos non inviara e-mail pro alcun del sequente functiones.',
+'emailauthenticated' => 'Tu adresse de e-mail ha essite confirmate le $2 a $3.',
+'emailnotauthenticated' => 'Tu non ha ancora confirmate tu adresse de e-mail.
+Nulle e-mail essera inviate pro le sequente functiones.',
'noemailprefs' => 'Es necessari specificar un adresse de e-mail in tu preferentias pro poter executar iste functiones.',
'emailconfirmlink' => 'Confirmar tu adresse de e-mail',
'invalidemailaddress' => 'Le adresse de e-mail ha un formato invalide e non pote esser acceptate.
'prefs-misc' => 'Misc',
'prefs-resetpass' => 'Cambiar contrasigno',
'prefs-changeemail' => 'Cambiar e-mail',
-'prefs-setemail' => 'Definir un adresse de e-mail',
+'prefs-setemail' => 'Specificar un adresse de e-mail',
'prefs-email' => 'Optiones de e-mail',
'prefs-rendering' => 'Apparentia',
'saveprefs' => 'Confirmar',
Si tu opta pro dar lo, isto essera usate pro dar te attribution pro tu contributiones.',
'prefs-help-email' => 'Le adresse de e-mail es optional, ma es necessari pro le reinitialisation de tu contrasigno, in caso que tu lo oblida.',
'prefs-help-email-others' => 'Tu pote etiam optar pro permitter que altere personas te contacta via tu pagina de usator o de discussion, sin necessitate de revelar tu identitate.',
-'prefs-help-email-required' => 'Le adresse de e-mail es requirite.',
+'prefs-help-email-required' => 'Un adresse de e-mail es obligatori.',
'prefs-info' => 'Informationes de base',
'prefs-i18n' => 'Internationalisation',
'prefs-signature' => 'Signatura',
Activa le button infra pro inviar un message de confirmation a tu adresse.
Le message includera un ligamine continente un codice;
visita le ligamine in tu navigator pro confirmar que tu adresse de e-mail es valide.',
-'confirmemail_pending' => 'Un codice de confirmation ha ja essite inviate a te;
-si tu ha recentemente create tu conto, es recommendate attender le arrivata de illo durante alcun minutas ante de provar requestar un nove codice.',
+'confirmemail_pending' => 'Un codice de confirmation ha jam essite inviate a te per e-mail;
+si tu ha create tu conto recentemente, per favor attende alcun minutas que le message de confirmation arriva ante de requestar un nove codice.',
'confirmemail_send' => 'Inviar un codice de confirmation',
'confirmemail_sent' => 'Message de confirmation inviate.',
'confirmemail_oncreate' => 'Un codice de confirmation ha essite inviate a tu adresse de e-mail.
'confirmemail_error' => 'Un problema occurreva durante le salveguarda de tu confirmation.',
'confirmemail_subject' => 'Confirmation del adresse de e-mail pro {{SITENAME}}',
'confirmemail_body' => 'Un persona, probabilemente tu, usante le adresse IP $1,
-ha registrate un conto "$2" con iste adresse de e-mail in {{SITENAME}}.
+ha create un conto "$2" con iste adresse de e-mail in {{SITENAME}}.
-Pro confirmar que iste conto es de facto tue, e pro activar le functiones
+Pro confirmar que iste conto es realmente tue, e pro activar le functiones
de e-mail in {{SITENAME}}, visita iste ligamine in tu navigator:
$3
-Si tu *non* ha registrate le conto, seque iste ligamine
+Si tu *non* ha create iste conto, seque le sequente ligamine
pro cancellar le confirmation del adresse de e-mail:
$5
'confirmemail_body_changed' => 'Un persona, probabilemente tu, usante le adresse IP $1,
ha cambiate le adresse de e-mail del conto "$2" a iste adresse in {{SITENAME}}.
-Pro confirmar que iste conto es de facto tue, e pro reactivar le functiones
+Pro confirmar que iste conto es realmente tue, e pro reactivar le functiones
de e-mail in {{SITENAME}}, visita iste ligamine in tu navigator:
$3
'confirmemail_body_set' => 'Un persona, probabilemente tu, usante le adresse IP $1,
ha specificate que iste adresse de e-mail pertine al conto "$2" in {{SITENAME}}.
-Pro confirmar que iste conto es de facto tue, e pro reactivar le functiones
+Pro confirmar que iste conto es realmente tue, e pro activar le functiones
de e-mail in {{SITENAME}}, visita iste ligamine in tu navigator:
$3
このメッセージを無視して、引き続き以前のパスワードを使用し続けることができます。',
'noemail' => '利用者「$1」のメールアドレスは登録されていません。',
'noemailcreate' => '有効なメールアドレスを入力する必要があります',
-'passwordsent' => '新しいパスワードを「$1」に登録されたメールアドレスに送信しました。
-ã\83¡ã\83¼ã\83«ã\82\92å\8f\97ã\81\91å\8f\96ã\81£たら、再度ログインしてください。',
+'passwordsent' => '新しいパスワードを「$1」に登録されたメールアドレスにお送りしました。
+ã\83¡ã\83¼ã\83«ã\81\8cå±\8aã\81\84たら、再度ログインしてください。',
'blocked-mailpassword' => 'ご使用中のIPアドレスからの編集はブロックされており、不正利用防止のため、パスワードの再発行機能は使用できません。',
'eauthentsent' => '指定したメールアドレスに、アドレス確認のためのメールをお送りしました。
メールに記載された手順に従って、このアカウントの所有者であることの確認が取れると、このアカウント宛のメールを受け取れるようになります。',
# Special:ChangeEmail
'changeemail' => 'メールアドレスの変更',
-'changeemail-header' => 'ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81®ã\83¡ã\83¼ã\83«ã\82¢ã\83\89ã\83¬ã\82¹ã\82\92変更',
+'changeemail-header' => 'ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81®ã\83¡ã\83¼ã\83«ã\82¢ã\83\89ã\83¬ã\82¹ã\81®変更',
'changeemail-text' => 'このフォームではメールアドレスを変更できます。この変更を確認するためにパスワードを入力する必要があります。',
'changeemail-no-info' => 'このページに直接アクセスするためにはログインしている必要があります。',
'changeemail-oldemail' => '現在のメールアドレス:',
'showingresults' => "'''$2''' 件目以降の最大 {{PLURAL:$1|'''$1''' 件の結果}}を表示しています。",
'showingresultsnum' => "'''$2''' 件目以降の {{PLURAL:$3|'''$3''' 件の結果}}を表示しています。",
'showingresultsheader' => "「'''$4'''」の検索結果 {{PLURAL:$5|'''$3''' 件中の '''$1''' 件目|'''$3''' 件中の '''$1''' 件目から '''$2''' 件目}}",
-'nonefound' => "'''注意''': 既定では一部の名前空間のみを検索します。
+'nonefound' => "'''注意:''' 既定では一部の名前空間のみを検索します。
''all:''を前に付けると、すべて (トークページやテンプレートなどを含む) を対象にできます。検索する名前空間を前に付けることもできます。",
'search-nonefound' => '問い合わせに合致する検索結果はありませんでした。',
'powersearch' => '高度な検索',
'unblockip' => 'ブロックを解除',
'unblockiptext' => '以下のフォームで利用者またはIPアドレスのブロックを解除できます。',
'ipusubmit' => 'このブロックを解除',
-'unblocked' => '[[User:$1|$1]]のブロックを解除しました',
-'unblocked-range' => '$1のブロックを解除しました',
-'unblocked-id' => 'ブロック$1を除去しました',
+'unblocked' => '[[User:$1|$1]]のブロックを解除しました。',
+'unblocked-range' => '$1のブロックを解除しました。',
+'unblocked-id' => 'ブロック$1を除去しました。',
'blocklist' => 'ブロックされている利用者',
'ipblocklist' => 'ブロックされている利用者',
'ipblocklist-legend' => 'ブロックされている利用者の検索',
この確認コードは $4 に期限切れになります。',
'confirmemail_invalidated' => 'メールアドレスの確認が中止されました',
-'invalidateemail' => 'メールアドレスの認証中止',
+'invalidateemail' => 'メールアドレスの確認中止',
# Scary transclusion
'scarytranscludedisabled' => '[ウィキ間の参照読み込みは無効になっています]',
'protectedpagetext' => 'Na pele vurnaisu rê qapan biya.',
'viewsourcetext' => 'Sıma şikinê çımê na pele bıvênê u kopya kerê:',
'protectedinterface' => "Na pele ''software'' rê meqalunê caunê bırnau dana, u qapana ke suıstımalu rê engel bo.",
-'editinginterface' => "'''Teme:''' Sıma hao jü pela ke serba nustê meqalunê caunê bırnau dana, vurnenê.
+'editinginterface' => "Teme:''' Sıma hawo jü pela ke serba nustê meqalunê caunê bırnau dana, vurnenê.
Vurnaisê na pele karberunê binu rê serpela karberi kena ke bıasno.
Serba çarnaişi, yardımê [//translatewiki.net/wiki/Main_Page?setlang=kiu translatewiki.net]i ra procêdoskerdene rê diqet kerê.",
'sqlhidden' => '(Persê SQLi nımıteo)',
'listgrouprights-addgroup-all' => 'Heme grubu ilawe ke',
'listgrouprights-removegroup-all' => 'Heme grubu wedare',
-# E-mail user
+# Email user
'emailuser' => 'Nê karberi rê e-poste bırusne',
'emailpage' => 'Karberi rê e-poste bırusne',
'emailfrom' => 'Kami ra:',
'thu' => 'Juğ',
'fri' => 'Vie',
'sat' => 'Shab',
-'january' => 'Jenero',
+'january' => 'Enero',
'february' => 'Hevrero',
'march' => 'Março',
'april' => 'Avril',
'tooltip-n-mainpage-description' => 'Visita la primera hoja',
'tooltip-n-portal' => 'Encima del projeto, lo que puedes hazer y ánde topar todo',
'tooltip-n-currentevents' => 'Información encima de los acontècimientos de oy día',
-'tooltip-n-recentchanges' => 'La lista de los trocamientos muevos en el viki',
+'tooltip-n-recentchanges' => 'Lista de los trocamientos muevos en el viki',
'tooltip-n-randompage' => 'Carga una hoja por asardo',
-'tooltip-n-help' => 'El lugar para saver más',
+'tooltip-n-help' => 'Para saver mas',
'tooltip-t-whatlinkshere' => 'Una lista de todas las hojas del viki que tienen atamientos con esta hoja',
'tooltip-t-recentchangeslinked' => 'Los trocamientos freskos de las hojas que tienen atamiento con esta hoja',
'tooltip-feed-rss' => 'Sindicación RSS de esta hoja',
'tooltip-t-contributions' => 'Ver la lista de ajustamientos de este usuario',
'tooltip-t-emailuser' => 'A este usuario, mándale una letra electrόnica (ímey)',
'tooltip-t-upload' => 'Suve dosyas por aquí',
-'tooltip-t-specialpages' => 'La lista de todas las hojas especiales',
+'tooltip-t-specialpages' => 'Lista de todas las hojas especiales',
'tooltip-t-print' => "Versión apropiada para imprimir d'esta hoja",
'tooltip-t-permalink' => "Atamiento permanente á est'enderechamiento de la hoja",
'tooltip-ca-nstab-main' => 'Ve el artícůlo de contènido',
# Bad image list
'bad_image_list' => 'El formato es ansina:
-Cale akavidar sólo elementos de lista (quere dezir: liñas que empeçan con *).
-El primer atamiento de cada liña deve de ser un atamiento á una dosya negra (á la dosya que se quere blokear).
-Los atamientos venideros que están en la mesma liña se aprecian como eksepsiones, por enxemplo, hojas ande la dosya se ve en la liña.',
+Sólo elementos de lista (liñas empeçando con *) se toman en konsidherasyón.
+El primer atamiento de cada liña deve de atarse con una dosya negra (la dosya que se quere blokar).
+Los atamientos venideros que están en la misma liña se konsidheran como eksepsiones (yaani hojas ande la dosya puede aparecer encaxada en la liña)',
# Metadata
'metadata' => 'Metadatos',
'thursday' => '週四',
'friday' => '週五',
'saturday' => '週六',
-'sun' => '週日',
-'mon' => '周一',
-'tue' => '周二',
-'wed' => '周三',
-'thu' => 'å\91¨å\9b\9b',
-'fri' => '周五',
-'sat' => 'å\91¨å\85',
+'sun' => '日',
+'mon' => '一',
+'tue' => '二',
+'wed' => '三',
+'thu' => '四',
+'fri' => '五',
+'sat' => '六',
'january' => '一月',
'february' => '二月',
'march' => '三月',
'ok' => '可',
'retrievedfrom' => '取自"$1"',
-'youhavenewmessages' => '子有$1($2)',
+'youhavenewmessages' => '有$1書至子書房也。($2)',
'newmessageslink' => '新訊',
'newmessagesdifflink' => '變更',
'youhavenewmessagesfromusers' => '子有 $1 自 {{PLURAL:$3|another user|$3 簿戶也}} ($2)。',
'loginlanguagelabel' => '語:$1',
'suspicious-userlogout' => '爾欲無離也,可由壞瀏覽器或快枝代理呈送之。',
-# E-mail sending
+# Email sending
'php-mail-error-unknown' => '於 PHP mail() 參數現錯',
# Change password dialog
'last' => '前',
'page_first' => '首',
'page_last' => '末',
-'histlegend' => "辨ç\95°ï¼\9aæ\93\87äº\8cå\94å¾\8c,按Enter、或點下鈕以辨之。<br />
-釋義:'''({{int:cur}})'''與今審辨;'''({{int:last}})'''與前審辨;'''{{int:minoreditletter}}''',校文",
+'histlegend' => "辨ç\95°ï¼\9aæ\97¢æ\93\87äº\8cå\94,按Enter、或點下鈕以辨之。<br />
+釋義:'''({{int:cur}})'''與今審辨;'''({{int:last}})'''與前審辨;'''{{int:minoreditletter}}''',令校",
'history-fieldset-title' => '誌覽',
'history-show-deleted' => '只刪',
'histfirst' => '初',
'prefs-displaywatchlist' => '示項',
'prefs-diffs' => '異',
-# User preference: e-mail validation using jQuery
+# User preference: email validation using jQuery
'email-address-validity-valid' => '電郵有效之',
'email-address-validity-invalid' => '貢一效之電郵',
'recentchanges-label-newpage' => '此纂開新頁',
'recentchanges-label-minor' => '此乃細纂',
'recentchanges-label-bot' => '此乃機纂',
-'recentchanges-label-unpatrolled' => 'æ¤ä¹\83æ\9cªå·¡ä¹\8bçº\82',
+'recentchanges-label-unpatrolled' => 'æ\98¯çº\82æ\9cªå·¡',
'rcnote' => "下為自$4$5起,'''$2'''日內'''$1'''近易也。",
'rcnotefrom' => "下為自'''$2'''至'''$1'''之易也。",
'rclistfrom' => '自$1起之易也',
'statistics-mostpopular' => '燴炙',
'disambiguations' => '釋義',
+'disambiguationspage' => 'Template:弭誤解',
'disambiguations-text' => '頁下引[[MediaWiki:Disambiguationspage]]模,求釋義,宜正題之。',
'doubleredirects' => '窮渡',
'listgrouprights-addgroup-self-all' => '加自之全組',
'listgrouprights-removegroup-self-all' => '除自之全組',
-# E-mail user
+# Email user
'mailnologin' => '無驛',
'mailnologintext' => '[[Special:UserLogin|登簿]]置郵,方可捎書。',
'emailuser' => '捎君',
'historywarning' => '警示,此頁約有誌$1:',
'confirmdeletetext' => '欲刪此物與誌,知後果、合[[{{MediaWiki:Policy-url}}]]後再為之。',
'actioncomplete' => '成矣',
-'actionfailed' => 'æ\95\97ç\9f£',
+'actionfailed' => 'æ\9cªç«\9f',
'deletedtext' => '"$1"刪矣,見誌刪於$2。',
'dellogpage' => '誌刪',
'dellogpagetext' => '近刪如下:',
'monthsall' => '全',
'limitall' => '全',
-# E-mail address confirmation
+# Email address confirmation
'confirmemail' => '核郵驛',
'confirmemail_noemail' => '[[Special:Preferences|簿註]]有驛。',
'confirmemail_send' => '遣核符',
'ipb-change-block' => 'Blokker brukaren på nytt med desse innstillingane',
'ipb-confirm' => 'Stadfest blokkering',
'badipaddress' => 'IP-adressa er ugyldig eller blokkering av brukarar er slått av på tenaren.',
-'blockipsuccesssub' => 'Blokkeringa er utførd',
+'blockipsuccesssub' => 'Blokkeringa er utført',
'blockipsuccesstext' => '«[[Special:Contributions/$1|$1]]» er blokkert.<br />
Sjå [[Special:BlockList|blokkeringslista]] for alle blokkeringane.',
'ipb-blockingself' => 'Du er i ferd med å blokkera deg sjølv. Er du viss på at du ynskjer gjera dette?',
'listingcontinuesabbrev' => 'Shown in contiuation of each first letter group. This message follows the first letter.
See http://test.wikipedia.org/wiki/Category:Test_ko?uselang={{SUBPAGENAME}}, for example.',
-'index-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__INDEX__</nowiki> behaviour switch are listed. For description of this behaviour switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].',
-'noindex-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__NOINDEX__</nowiki> behaviour switch are listed. For description of this behaviour switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].',
+'index-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__INDEX__</nowiki> behavior switch are listed. For description of this behavior switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].',
+'noindex-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__NOINDEX__</nowiki> behavior switch are listed. For description of this behavior switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].',
'broken-file-category' => 'Name of [[mw:Help:Tracking categories|tracking category]] where pages that embed files that do not exist ("broken images") are listed.',
'categoryviewer-pagedlinks' => '{{Optional}}
The pagination links in category viewer. Parameters:
'duration-centuries' => '{{Related|Duration}}',
'duration-millennia' => '{{Related|Duration}}',
+# Rotation
+'rotation-comment' => 'comment set for new version uploaded after rotation',
+
# Unknown messages
'pageswithprop-legend' => 'Legend for the input form on [[Special:PagesWithProp]].
{{Identical|Page with page property}}',
'logentry-patrol-patrol-auto' => '$1 автоматически {{GENDER:$1|отпатрулировал|отпатрулировала}} версию $4 страницы $3',
'logentry-newusers-newusers' => 'Создана учётная запись $1',
'logentry-newusers-create' => 'Создана учётная запись $1',
-'logentry-newusers-create2' => '$1 {{GENDER:$2|создал|создала}} учётную запись для $3',
-'logentry-newusers-byemail' => 'Учетная запись пользователя $3 была создана $1 и пароль был отправлен по электронной почте',
+'logentry-newusers-create2' => '$1 {{GENDER:$2|создал|создала}} учётную запись $3',
+'logentry-newusers-byemail' => '$1 {{GENDER:$2|создал|создала}} учётную запись $3 и пароль был отправлен по электронной почте',
'logentry-newusers-autocreate' => 'Автоматически создана учётная запись $1',
'logentry-rights-rights' => '$1 {{GENDER:$1|изменил|изменила}} членство в группах для $3 с $4 на $5',
'logentry-rights-rights-legacy' => '$1 {{GENDER:$1|изменил|изменила}} членство в группах для $3',
[[Special:Preferences|{{SITENAME}} tercihlerinizi]] değiştirmeyi unutmayın.',
'yourname' => 'Kullanıcı adı:',
'yourpassword' => 'Parola:',
-'yourpasswordagain' => 'Parolayı yeniden yaz:',
+'yourpasswordagain' => 'Parolayı yeniden girin:',
'remembermypassword' => 'Girişimi bu tarayıcıda hatırla (en fazla $1 {{PLURAL:$1|gün|gün}} için)',
'securelogin-stick-https' => "Giriş yaptıktan sonra HTTPS'e bağlı kal",
'yourdomainname' => 'Alan adınız:',
'prefs-help-gender' => 'İsteğe bağlı: Yazılım tarafından doğru cinsiyet adreslemesi için kullanılır. Bu bilgi umumi olacaktır.',
'email' => 'E-posta',
'prefs-help-realname' => '* Gerçek isim (isteğe bağlı): eğer gerçek isminizi vermeyi seçerseniz, çalışmanızı size atfederken kullanılacaktır.',
-'prefs-help-email' => 'E-posta adresi isteğe bağlıdır; ancak eğer parolanızı unutursanız e-posta adresinize yeni parola gönderilmesine olanak sağlar.',
+'prefs-help-email' => 'E-posta adresi isteğe bağlıdır; ancak parolanızı unutmanız durumunda parola sıfırlamak için gerekecektir.',
'prefs-help-email-others' => 'Ayrıca kullanıcı sayfanızdaki bir bağlantı yoluyla diğer kullanıcıların size e-posta atmasına izin vermeyi seçebilirsiniz.
Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz açıklanmaz.',
'prefs-help-email-required' => 'E-posta adresi gerekmektedir.',
'loginlanguagelabel' => 'Тел: $1',
'suspicious-userlogout' => 'Сезнең эшчәнлекне бетерү соравыгыз кире кагылды, чөнки ул ялгыш браузер яисә кэшлаучы прокси аша җибәрелергэ мөмкин.',
-# E-mail sending
+# Email sending
'php-mail-error-unknown' => 'PHP mail() функциясендә билгесез хата',
'user-mail-no-addy' => 'Электрон почта адресыннан башка электрон хат җибәрмәкче булды',
'listgrouprights-helppage' => 'Help:Төркемнәрнең хокуклары',
'listgrouprights-members' => '(төркем исемлеге)',
-# E-mail user
+# Email user
'emailuser' => 'Бу кулланучыга хат',
'emailuser-title-target' => '{{GENDER:$1|Кулланучыга}} электрон хат язу',
'emailuser-title-notarget' => 'Кулланучыга хат җибәрү',
'hijri-calendar-m7' => 'Раҗәб',
'hijri-calendar-m9' => 'Рамазан',
+# Signatures
+'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|бәхәс]])',
+
# Core parser functions
'duplicate-defaultsort' => 'Игътибар. Уйланма куелган "$2" бүлгәләү ачкычы элеккеге уйланма куелган "$1" бүлгәләү ачкычын үзгәртә.',
$messages = array(
# User preference toggles
'tog-underline' => 'Havolalarning tagiga chizish:',
-'tog-justify' => "Matnni sahifaning eni bo'yicha tekislash",
-'tog-hideminor' => "Yangi oʻzgarishlar ro'yxatida kichik tahrirlarni yashirish",
-'tog-hidepatrolled' => 'Yangi oʻzgarishlar roʻyxatida patrullangan tahrirlarni yashirish',
-'tog-newpageshidepatrolled' => "Yangi sahifalar ro'yxatida patrullangan sahifalarni yashirish",
-'tog-numberheadings' => 'Sarlavhalarni avtomatik tarzda raqamlash',
-'tog-showtoolbar' => "Tahrirlash vaqtida yuqorigi unsurlar darchasini ko'rsatish (JavaScript)",
-'tog-editsection' => "[tahrir] havolasini har bir seksiyada ko'rsatish",
-'tog-showtoc' => "Mundarijani ko'rsatish (3 ta sarlavhadan ko'p bo'lgan sahifalar uchun)",
-'tog-rememberpassword' => 'Hisob ma’lumotlarini ushbu kompyuterda eslab qolish (eng ko‘pi bilan $1 {{PLURAL:$1|kunga|kunga}})',
+'tog-justify' => 'Matnni sahifaning eni boʻyicha tekislash',
+'tog-hideminor' => 'Yangi oʻzgarishlar roʻyxatida kichik tahrirlarni yashirish',
+'tog-hidepatrolled' => 'Yangi oʻzgarishlar roʻyxatida tekshirilgan tahrirlarni yashirish',
+'tog-newpageshidepatrolled' => 'Yangi sahifalar roʻyxatida tekshirilgan sahifalarni yashirish',
+'tog-extendwatchlist' => 'Kengaytirilgan kuzatuv roʻyxati: faqat oxirgi paytdagi emas, barcha oʻzgarishlar koʻrsatiladi',
+'tog-usenewrc' => 'Yangi oʻzgarishlar va kuzatuv roʻyxatidagi sahifalarni guruhlarga boʻlish (JavaScript orqali)',
+'tog-numberheadings' => 'Sarlavhalarni avtomatik raqamlash',
+'tog-showtoolbar' => 'Tahrirlash asboblari joylashgan yoʻlakchani koʻrsatish (JavaScript orqali)',
+'tog-editondblclick' => 'Sichqoncha tugmasini ikki martagina bosib tahrirlashni boshlash',
+'tog-editsection' => '[tahrir] havolasini har bir boʻlim boshida koʻrsatish',
+'tog-editsectiononrightclick' => 'Boʻlim sarlavhasiga sichqonchaning oʻng tugmasi bilan bosib tahrirlashni boshlash',
+'tog-showtoc' => 'Mundarijani koʻrsatish (3 tadan koʻproq sarlavha bor sahifalarda)',
+'tog-rememberpassword' => 'Hisob ma’lumotlarim ushbu brauzerda eslab qolinsin (ko‘pi bilan $1 {{PLURAL:$1|kunga|kunga}})',
'tog-watchcreations' => 'Men yaratgan sahifalarni va yuklagan fayllarni kuzatuv roʻyxatimga qoʻsh',
'tog-watchdefault' => 'Men tahrirlagan sahifa va fayllarni kuzatuv roʻyxatimga qoʻsh',
'tog-watchmoves' => 'Men koʻchirgan sahifa va fayllarni kuzatuv roʻyxatimga qoʻsh',
-'tog-watchdeletion' => 'Men yoʻqotgan sahifa va fayllarni kuzatuv roʻyxatimga qoʻsh',
-'tog-minordefault' => "Boshlang'ich holatga barcha tahrirlarni kamahamiyatli qilib belgilash",
-'tog-previewontop' => "Oldindan ko'rishni tahrirlash oynasi oldiga joylashtirish",
-'tog-previewonfirst' => "Tahrirlashga o'tishda batafsil ko'rinishni ko'rsatish",
-'tog-nocache' => "Brauzerda sahifalarni keshda saqlashni o'chirish",
+'tog-watchdeletion' => 'Men oʻchirgan sahifa va fayllarni kuzatuv roʻyxatimga qoʻsh',
+'tog-minordefault' => 'Sukut boʻyicha barcha tahrirlarimni «kichik tahrir» etib belgilash',
+'tog-previewontop' => 'Tahrir oynasi tepasida koʻrib chiqish',
+'tog-previewonfirst' => 'Tahrirlashga oʻtiboq koʻrib chiqishni boshlash',
+'tog-nocache' => 'Brauzer sahifalarni kesh xotirasida saqlamasin',
'tog-enotifwatchlistpages' => 'Kuzatuv roʻyxatimdagi sahifa yoki fayllar oʻzgartirilsa, e-pochtamga bu haqda xat yuborilsin',
'tog-enotifusertalkpages' => 'Munozara sahifam oʻzgartirilsa, e-pochtamga bu haqda xat yuborilsin',
'tog-oldsig' => 'Joriy imzo:',
-'tog-fancysig' => 'Imzoni wikimatn sifatida qara (avtomatik ishoratsiz)',
-'tog-showjumplinks' => '"ga o\'tish" yordamchi havolalarini yoqish',
-'tog-ccmeonemails' => 'Men boshqa foydalanuvchilarga yuborayotgan xatnig nusxasi oʻzimning e-pochtamga ham yuborilsin',
+'tog-fancysig' => 'Imzoni viki-belgi qilib koʻrsatish (avtomatik ishoratsiz)',
+'tog-showjumplinks' => 'yordamchi "tez oʻtish" havolalarini yoqish',
+'tog-ccmeonemails' => 'Boshqa ishtirokchilarga yozgan xatimning nusxasi oʻzimning e-pochtamga joʻnatilsin.',
'tog-showhiddencats' => 'Yashirin turkumlarni koʻrsatish',
'tog-noconvertlink' => "Sarlavhaga aylantirish dastagini o'chirib qo'yish",
'yourname' => 'Foydalanuvchi nomi',
'yourpassword' => 'Maxfiy soʻz',
'yourpasswordagain' => 'Maxfiy so‘zni qayta kiriting:',
-'remembermypassword' => 'Hisob ma’lumotlarini ushbu kompyuterda eslab qolish (eng ko‘pi bilan $1 {{PLURAL:$1|kun|kun}} uchun)',
+'remembermypassword' => 'Hisob ma’lumotlarim ushbu brauzerda eslab qolinsin (ko‘pi bilan $1 {{PLURAL:$1|kunga|kunga}})',
'securelogin-stick-https' => "Kirgandan keyin HTTPS bo'yicha ulanishni davom ettirish",
'yourdomainname' => 'Sizning domeningiz:',
'password-change-forbidden' => "Siz bu vikida maxfiy so'zni o'zgartira olmaysiz.",
'emailsubject' => 'Sarlavha:',
'emailmessage' => 'Xabar',
'emailsend' => 'Joʻnatish',
-'emailccme' => 'Maktub nusxasini menga joʻnatish',
+'emailccme' => 'Maktub nusxasi mening elektron pochtamga joʻnatilsin',
'emailccsubject' => '$1ga maktubingizning nusxasi: $2',
'emailsent' => "Xat jo'natildi",
'emailsenttext' => "Sizning elektron maktubingiz jo'natildi.",
Agar siz bu sahifani kuzatuv ro'yxatingizdan o'chirmoqchi bo'lsangiz \"Kuzatmaslik\" yozuvini bosing.",
'removewatch' => "Kuzatuv ro'yxatidan o'chirish",
-'removedwatchtext' => '"[[:$1]]" sahifasi kuzatuv ro\'yxatingizdan o\'chirildi.',
+'removedwatchtext' => '"[[:$1]]" sahifasi [[Special:Watchlist|kuzatuv roʻyxatingizdan]] oʻchirildi.',
'watch' => 'Kuzatish',
'watchthispage' => 'Sahifani kuzatish',
'unwatch' => 'Kuzatmaslik',
'userpage' => 'Xem trang thành viên',
'projectpage' => 'Xem trang dự án',
'imagepage' => 'Xem trang tập tin',
-'mediawikipage' => 'Thông báo giao diện',
+'mediawikipage' => 'Thông điệp giao diện',
'templatepage' => 'Trang bản mẫu',
'viewhelppage' => 'Trang trợ giúp',
'categorypage' => 'Trang thể loại',
'nstab-special' => 'Trang đặc biệt',
'nstab-project' => 'Dự án',
'nstab-image' => 'Tập tin',
-'nstab-mediawiki' => 'Thông báo',
+'nstab-mediawiki' => 'Thông điệp',
'nstab-template' => 'Bản mẫu',
'nstab-help' => 'Trợ giúp',
'nstab-category' => 'Thể loại',
'protectedpagetext' => 'Trang này đã bị khóa không cho sửa đổi hoặc tác động khác.',
'viewsourcetext' => 'Bạn vẫn có thể xem và chép xuống mã nguồn của trang này:',
'viewyourtext' => "Bạn vẫn có thể xem và chép xuống mã nguồn '''các sửa đổi của bạn''' tại trang này:",
-'protectedinterface' => 'Trang này cung cấp một thông báo trong giao diện phần mềm, và bị khóa để tránh phá hoại. Để bổ sung hoặc thay đổi bản dịch ở bất cứ wiki nào, xin vui lòng đóng góp vào [//translatewiki.net/wiki/Main_Page?setlang=vi translatewiki.net], dự án bản địa hóa của MediaWiki.',
-'editinginterface' => "'''Lưu ý:''' Bạn đang sửa chữa một trang dùng để cung cấp thông báo giao diện cho phần mềm. Những thay đổi tại trang này sẽ ảnh hưởng đến giao diện của rất nhiều người dùng wiki này. Để bổ sung hoặc thay đổi bản dịch ở bất cứ wiki nào, xin vui lòng đóng góp vào [//translatewiki.net/wiki/Main_Page?setlang=vi translatewiki.net], dự án bản địa hóa của MediaWiki.",
+'protectedinterface' => 'Trang này cung cấp một thông điệp trong giao diện phần mềm, và bị khóa để tránh phá hoại. Để bổ sung hoặc thay đổi bản dịch ở bất cứ wiki nào, xin vui lòng đóng góp vào [//translatewiki.net/wiki/Main_Page?setlang=vi translatewiki.net], dự án bản địa hóa của MediaWiki.',
+'editinginterface' => "'''Lưu ý:''' Bạn đang sửa chữa một trang dùng để cung cấp thông điệp giao diện cho phần mềm. Những thay đổi tại trang này sẽ ảnh hưởng đến giao diện của rất nhiều người dùng wiki này. Để bổ sung hoặc thay đổi bản dịch ở bất cứ wiki nào, xin vui lòng đóng góp vào [//translatewiki.net/wiki/Main_Page?setlang=vi translatewiki.net], dự án bản địa hóa của MediaWiki.",
'sqlhidden' => '(đã giấu truy vấn SQL)',
'cascadeprotected' => 'Trang này đã bị khóa không cho sửa đổi, vì nó được nhúng vào {{PLURAL:$1|trang|những trang}} đã bị khóa với tùy chọn “khóa theo tầng” được kích hoạt:
$2',
'createaccount-title' => 'Tài khoản mới tại {{SITENAME}}',
'createaccount-text' => 'Ai đó đã tạo một tài khoản với tên $2 tại {{SITENAME}} ($4). Mật khẩu của "$2" là "$3". Bạn nên đăng nhập và đổi mật khẩu ngay bây giờ.
-Xin hãy bỏ qua thông báo này nếu tài khoản này không phải do bạn tạo ra.',
+Xin hãy bỏ qua thông điệp này nếu tài khoản này không phải do bạn tạo ra.',
'usernamehasherror' => 'Tên người dùng không thể chứa dấu rào',
'login-throttled' => 'Bạn đã thử quá nhiều mật khẩu của tài khoản này.
Xin hãy đợi chốc lát rồi thử lại.',
'expensive-parserfunction-category' => 'Trang có quá nhiều lời gọi hàm cú pháp cần mức độ xử lý cao',
'post-expand-template-inclusion-warning' => 'Cảnh báo: Kích thước bản mẫu nhúng vào quá lớn.
Một số bản mẫu sẽ không được đưa vào.',
-'post-expand-template-inclusion-category' => 'Những trang có kích thước bản mẫu nhúng vào vượt quá giới hạn cho phép',
-'post-expand-template-argument-warning' => 'Cảnh báo: Trang này có chứa ít nhất một giá trị bản mẫu có kích thước bung ra quá lớn.
-Những giá trị này sẽ bị bỏ đi.',
-'post-expand-template-argument-category' => 'Những trang có chứa những giá trị bản mẫu bị loại bỏ',
+'post-expand-template-inclusion-category' => 'Trang có kích thước bản mẫu nhúng vào vượt quá giới hạn cho phép',
+'post-expand-template-argument-warning' => 'Cảnh báo: Trang này có chứa ít nhất một tham số bản mẫu có kích thước bung ra quá lớn.
+Những tham số này sẽ bị bỏ đi.',
+'post-expand-template-argument-category' => 'Trang có chứa tham số bản mẫu bị loại bỏ',
'parser-template-loop-warning' => 'Phát hiện bản mẫu lặp vòng: [[$1]]',
'parser-template-recursion-depth-warning' => 'Bản mẫu đã vượt quá giới hạn về độ sâu đệ quy ($1)',
'language-converter-depth-warning' => 'Đã vượt quá giới hạn độ sâu của bộ chuyển đổi ngôn ngữ ($1)',
'emailuserfooter' => 'Thư điện tử này được $1 gửi đến $2 thông qua chức năng “Gửi thư cho người này” của {{SITENAME}}.',
# User Messenger
-'usermessage-summary' => 'Đang để lại thông báo hệ thống.',
-'usermessage-editor' => 'Trình thông báo hệ thống',
+'usermessage-summary' => 'Đang để lại thông điệp hệ thống.',
+'usermessage-editor' => 'Trình thông điệp hệ thống',
# Watchlist
'watchlist' => 'Danh sách theo dõi',
'export-pagelinks' => 'Gồm cả các trang liên kết sâu đến:',
# Namespace 8 related
-'allmessages' => 'Thông báo hệ thống',
-'allmessagesname' => 'Tên thông báo',
+'allmessages' => 'Thông điệp hệ thống',
+'allmessagesname' => 'Tên thông điệp',
'allmessagesdefault' => 'Nội dung mặc định',
'allmessagescurrent' => 'Nội dung hiện thời',
-'allmessagestext' => 'Đây là toàn bộ thông báo hệ thống có trong không gian tên MediaWiki.
-Mời vào [//www.mediawiki.org/wiki/Localisation Địa phương hóa MediaWiki] và [//translatewiki.net translatewiki.net] nếu bạn muốn đóng góp dịch chung cả MediaWiki.',
+'allmessagestext' => 'Đây là toàn bộ thông điệp hệ thống có trong không gian tên MediaWiki.
+Mời vào [//www.mediawiki.org/wiki/Localisation?uselang=vi Địa phương hóa MediaWiki] và [//translatewiki.net/wiki/?uselang=vi translatewiki.net] nếu bạn muốn đóng góp dịch chung cả MediaWiki.',
'allmessagesnotsupportedDB' => "Trang này không dùng được vì biến '''\$wgUseDatabaseMessages''' đã bị tắt.",
'allmessages-filter-legend' => 'Bộ lọc',
'allmessages-filter' => 'Lọc theo tình trạng sửa đổi:',
'tooltip-t-specialpages' => 'Danh sách các trang đặc biệt',
'tooltip-t-print' => 'Bản để in ra của trang',
'tooltip-t-permalink' => 'Liên kết thường trực đến phiên bản này của trang',
-'tooltip-ca-nstab-main' => 'Xem trang nội dung này',
-'tooltip-ca-nstab-user' => 'Xem trang về người này',
+'tooltip-ca-nstab-main' => 'Xem trang nội dung',
+'tooltip-ca-nstab-user' => 'Xem trang cá nhân',
'tooltip-ca-nstab-media' => 'Xem trang phương tiện',
'tooltip-ca-nstab-special' => 'Đây là một trang đặc biệt, bạn không thể sửa đổi nó.',
'tooltip-ca-nstab-project' => 'Xem trang dự án',
'tooltip-ca-nstab-image' => 'Xem trang miêu tả tập tin',
-'tooltip-ca-nstab-mediawiki' => 'Xem thông báo hệ thống',
+'tooltip-ca-nstab-mediawiki' => 'Xem thông điệp hệ thống',
'tooltip-ca-nstab-template' => 'Xem bản mẫu',
'tooltip-ca-nstab-help' => 'Xem trang trợ giúp',
'tooltip-ca-nstab-category' => 'Xem trang thể loại',
'filehist-filesize' => '檔案大小',
'filehist-comment' => '註解',
'filehist-missing' => '檔案遺失',
-'imagelinks' => 'æ\96\87件使用情況',
+'imagelinks' => 'æª\94æ¡\88使用情況',
'linkstoimage' => '以下的$1個頁面連接到本檔案:',
'linkstoimage-more' => '多於$1個頁面連接到這個檔案。
下面的清單只列示了連去這個檔案的最首$1個頁面。
runJobs.php
Immediately complete all jobs in the job queue
- stats.php
+ showCacheStats.php
Show all statistics stored in the cache
undelete.php
Update pages restriction to the new schema
userOptions.php
- Change user options
\ No newline at end of file
+ Change user options
--- /dev/null
+<?php
+/**
+ * Removes all statistics tracking from the cache.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once( __DIR__ . '/Maintenance.php' );
+
+/**
+ * Maintenance script to remove all statistics tracking from the cache.
+ *
+ * @ingroup Maintenance
+ */
+class ClearCacheStats extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Remove all statistics tracking from the cache";
+ }
+
+ public function execute() {
+ global $wgLocalDatabases, $wgMemc;
+ foreach ( $wgLocalDatabases as $db ) {
+ $wgMemc->delete( "$db:stats:request_with_session" );
+ $wgMemc->delete( "$db:stats:request_without_session" );
+ $wgMemc->delete( "$db:stats:pcache_hit" );
+ $wgMemc->delete( "$db:stats:pcache_miss_expired" );
+ $wgMemc->delete( "$db:stats:pcache_miss_absent" );
+ $wgMemc->delete( "$db:stats:pcache_miss_stub" );
+ $wgMemc->delete( "$db:stats:image_cache_hit" );
+ $wgMemc->delete( "$db:stats:image_cache_miss" );
+ $wgMemc->delete( "$db:stats:image_cache_update" );
+ $wgMemc->delete( "$db:stats:diff_cache_hit" );
+ $wgMemc->delete( "$db:stats:diff_cache_miss" );
+ $wgMemc->delete( "$db:stats:diff_uncacheable" );
+ $wgMemc->delete( "$db:stats:job-insert" );
+ $wgMemc->delete( "$db:stats:job-pop" );
+ }
+ }
+}
+
+$maintClass = "ClearCacheStats";
+require_once( RUN_MAINTENANCE_IF_MAIN );
--- /dev/null
+<?php
+/**
+ * Clear the cache of interwiki prefixes for all local wikis.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once( __DIR__ . '/Maintenance.php' );
+
+/**
+ * Maintenance script to clear the cache of interwiki prefixes for all local wikis.
+ *
+ * @ingroup Maintenance
+ */
+class ClearInterwikiCache extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Clear all interwiki links for all languages from the cache";
+ }
+
+ public function execute() {
+ global $wgLocalDatabases, $wgMemc;
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false );
+ $prefixes = array();
+ foreach ( $res as $row ) {
+ $prefixes[] = $row->iw_prefix;
+ }
+
+ foreach ( $wgLocalDatabases as $db ) {
+ $this->output( "$db..." );
+ foreach ( $prefixes as $prefix ) {
+ $wgMemc->delete( "$db:interwiki:$prefix" );
+ }
+ $this->output( "done\n" );
+ }
+ }
+}
+
+$maintClass = "ClearInterwikiCache";
+require_once( RUN_MAINTENANCE_IF_MAIN );
+++ /dev/null
-<?php
-/**
- * Clear the cache of interwiki prefixes for all local wikis.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- */
-
-require_once( __DIR__ . '/Maintenance.php' );
-
-/**
- * Maintenance script to clear the cache of interwiki prefixes for all local wikis.
- *
- * @ingroup Maintenance
- */
-class ClearInterwikiCache extends Maintenance {
-
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Clear all interwiki links for all languages from the cache";
- }
-
- public function execute() {
- global $wgLocalDatabases, $wgMemc;
- $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false );
- $prefixes = array();
- foreach ( $res as $row ) {
- $prefixes[] = $row->iw_prefix;
- }
-
- foreach ( $wgLocalDatabases as $db ) {
- $this->output( "$db..." );
- foreach ( $prefixes as $prefix ) {
- $wgMemc->delete( "$db:interwiki:$prefix" );
- }
- $this->output( "done\n" );
- }
- }
-}
-
-$maintClass = "ClearInterwikiCache";
-require_once( RUN_MAINTENANCE_IF_MAIN );
+++ /dev/null
-<?php
-/**
- * Removes all statistics tracking from the cache.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- */
-
-require_once( __DIR__ . '/Maintenance.php' );
-
-/**
- * Maintenance script to remove all statistics tracking from the cache.
- *
- * @ingroup Maintenance
- */
-class clear_stats extends Maintenance {
-
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Remove all statistics tracking from the cache";
- }
-
- public function execute() {
- global $wgLocalDatabases, $wgMemc;
- foreach ( $wgLocalDatabases as $db ) {
- $wgMemc->delete( "$db:stats:request_with_session" );
- $wgMemc->delete( "$db:stats:request_without_session" );
- $wgMemc->delete( "$db:stats:pcache_hit" );
- $wgMemc->delete( "$db:stats:pcache_miss_expired" );
- $wgMemc->delete( "$db:stats:pcache_miss_absent" );
- $wgMemc->delete( "$db:stats:pcache_miss_stub" );
- $wgMemc->delete( "$db:stats:image_cache_hit" );
- $wgMemc->delete( "$db:stats:image_cache_miss" );
- $wgMemc->delete( "$db:stats:image_cache_update" );
- $wgMemc->delete( "$db:stats:diff_cache_hit" );
- $wgMemc->delete( "$db:stats:diff_cache_miss" );
- $wgMemc->delete( "$db:stats:diff_uncacheable" );
- $wgMemc->delete( "$db:stats:job-insert" );
- $wgMemc->delete( "$db:stats:job-pop" );
- }
- }
-}
-
-$maintClass = "clear_stats";
-require_once( RUN_MAINTENANCE_IF_MAIN );
--- /dev/null
+<?php
+/**
+ * Re-initialise or update the site statistics table.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ * @author Brion Vibber
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+require_once( __DIR__ . '/Maintenance.php' );
+
+/**
+ * Maintenance script to re-initialise or update the site statistics table
+ *
+ * @ingroup Maintenance
+ */
+class InitSiteStats extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Re-initialise the site statistics tables";
+ $this->addOption( 'update', 'Update the existing statistics (preserves the ss_total_views field)' );
+ $this->addOption( 'noviews', "Don't update the page view counter" );
+ $this->addOption( 'active', 'Also update active users count' );
+ $this->addOption( 'use-master', 'Count using the master database' );
+ }
+
+ public function execute() {
+ $this->output( "Refresh Site Statistics\n\n" );
+ $counter = new SiteStatsInit( $this->hasOption( 'use-master' ) );
+
+ $this->output( "Counting total edits..." );
+ $edits = $counter->edits();
+ $this->output( "{$edits}\nCounting number of articles..." );
+
+ $good = $counter->articles();
+ $this->output( "{$good}\nCounting total pages..." );
+
+ $pages = $counter->pages();
+ $this->output( "{$pages}\nCounting number of users..." );
+
+ $users = $counter->users();
+ $this->output( "{$users}\nCounting number of images..." );
+
+ $image = $counter->files();
+ $this->output( "{$image}\n" );
+
+ if ( !$this->hasOption( 'noviews' ) ) {
+ $this->output( "Counting total page views..." );
+ $views = $counter->views();
+ $this->output( "{$views}\n" );
+ }
+
+ if ( $this->hasOption( 'active' ) ) {
+ $this->output( "Counting active users..." );
+ $active = SiteStatsUpdate::cacheUpdate( wfGetDB( DB_MASTER ) );
+ $this->output( "{$active}\n" );
+ }
+
+ $this->output( "\nUpdating site statistics..." );
+
+ if ( $this->hasOption( 'update' ) ) {
+ $counter->update();
+ } else {
+ $counter->refresh();
+ }
+
+ $this->output( "done.\n" );
+ }
+}
+
+$maintClass = "InitSiteStats";
+require_once( RUN_MAINTENANCE_IF_MAIN );
+++ /dev/null
-<?php
-/**
- * Re-initialise or update the site statistics table.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Brion Vibber
- * @author Rob Church <robchur@gmail.com>
- */
-
-require_once( __DIR__ . '/Maintenance.php' );
-
-/**
- * Maintenance script to re-initialise or update the site statistics table
- *
- * @ingroup Maintenance
- */
-class InitStats extends Maintenance {
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Re-initialise the site statistics tables";
- $this->addOption( 'update', 'Update the existing statistics (preserves the ss_total_views field)' );
- $this->addOption( 'noviews', "Don't update the page view counter" );
- $this->addOption( 'active', 'Also update active users count' );
- $this->addOption( 'use-master', 'Count using the master database' );
- }
-
- public function execute() {
- $this->output( "Refresh Site Statistics\n\n" );
- $counter = new SiteStatsInit( $this->hasOption( 'use-master' ) );
-
- $this->output( "Counting total edits..." );
- $edits = $counter->edits();
- $this->output( "{$edits}\nCounting number of articles..." );
-
- $good = $counter->articles();
- $this->output( "{$good}\nCounting total pages..." );
-
- $pages = $counter->pages();
- $this->output( "{$pages}\nCounting number of users..." );
-
- $users = $counter->users();
- $this->output( "{$users}\nCounting number of images..." );
-
- $image = $counter->files();
- $this->output( "{$image}\n" );
-
- if ( !$this->hasOption( 'noviews' ) ) {
- $this->output( "Counting total page views..." );
- $views = $counter->views();
- $this->output( "{$views}\n" );
- }
-
- if ( $this->hasOption( 'active' ) ) {
- $this->output( "Counting active users..." );
- $active = SiteStatsUpdate::cacheUpdate( wfGetDB( DB_MASTER ) );
- $this->output( "{$active}\n" );
- }
-
- $this->output( "\nUpdating site statistics..." );
-
- if ( $this->hasOption( 'update' ) ) {
- $counter->update();
- } else {
- $counter->refresh();
- }
-
- $this->output( "done.\n" );
- }
-}
-
-$maintClass = "InitStats";
-require_once( RUN_MAINTENANCE_IF_MAIN );
$wgBlockComments = array(
'sidebar' => "The sidebar for MonoBook is generated from this message, lines that do not
begin with * or ** are discarded, furthermore lines that do begin with ** and
-do not contain | are also discarded, but do not depend on this behaviour for
+do not contain | are also discarded, but do not depend on this behavior for
future releases. Also note that since each list value is wrapped in a unique
XHTML id it should only appear once and include characters that are legal
XHTML id names.",
'apierrors' => 'API errors',
'duration' => 'Durations',
'cachedspecial' => 'SpecialCachedPage',
+ 'rotation-comment' => 'Image rotation message',
);
--- /dev/null
+<?php
+/**
+ * Command line script to check for an open proxy at a specified location.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+if( PHP_SAPI != 'cli' ) {
+ die( 1 );
+}
+
+/**
+ *
+ */
+$output = '';
+
+/**
+ * Exit if there are not enough parameters, or if it's not command line mode
+ */
+if ( ( isset( $_REQUEST ) && array_key_exists( 'argv', $_REQUEST ) ) || count( $argv ) < 4 ) {
+ $output .= "Incorrect parameters\n";
+} else {
+ /**
+ * Get parameters
+ */
+ $ip = $argv[1];
+ $port = $argv[2];
+ $url = $argv[3];
+ $host = trim(`hostname`);
+ $output = "Connecting to $ip:$port, target $url, this hostname $host\n";
+
+ # Open socket
+ $sock = @fsockopen($ip, $port, $errno, $errstr, 5);
+ if ($errno == 0 ) {
+ $output .= "Connected\n";
+ # Send payload
+ $request = "GET $url HTTP/1.0\r\n";
+# $request .= "Proxy-Connection: Keep-Alive\r\n";
+# $request .= "Pragma: no-cache\r\n";
+# $request .= "Host: ".$url."\r\n";
+# $request .= "User-Agent: MediaWiki open proxy check\r\n";
+ $request .= "\r\n";
+ @fputs($sock, $request);
+ $response = fgets($sock, 65536);
+ $output .= $response;
+ @fclose($sock);
+ } else {
+ $output .= "No connection\n";
+ }
+}
+
+$output = escapeshellarg( $output );
+
+#`echo $output >> /home/tstarling/open/proxy.log`;
+++ /dev/null
-<?php
-/**
- * Command line script to check for an open proxy at a specified location.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- */
-
-if( PHP_SAPI != 'cli' ) {
- die( 1 );
-}
-
-/**
- *
- */
-$output = '';
-
-/**
- * Exit if there are not enough parameters, or if it's not command line mode
- */
-if ( ( isset( $_REQUEST ) && array_key_exists( 'argv', $_REQUEST ) ) || count( $argv ) < 4 ) {
- $output .= "Incorrect parameters\n";
-} else {
- /**
- * Get parameters
- */
- $ip = $argv[1];
- $port = $argv[2];
- $url = $argv[3];
- $host = trim(`hostname`);
- $output = "Connecting to $ip:$port, target $url, this hostname $host\n";
-
- # Open socket
- $sock = @fsockopen($ip, $port, $errno, $errstr, 5);
- if ($errno == 0 ) {
- $output .= "Connected\n";
- # Send payload
- $request = "GET $url HTTP/1.0\r\n";
-# $request .= "Proxy-Connection: Keep-Alive\r\n";
-# $request .= "Pragma: no-cache\r\n";
-# $request .= "Host: ".$url."\r\n";
-# $request .= "User-Agent: MediaWiki open proxy check\r\n";
- $request .= "\r\n";
- @fputs($sock, $request);
- $response = fgets($sock, 65536);
- $output .= $response;
- @fclose($sock);
- } else {
- $output .= "No connection\n";
- }
-}
-
-$output = escapeshellarg( $output );
-
-#`echo $output >> /home/tstarling/open/proxy.log`;
$this->runJobsLog( "Executed $count periodic queue task(s)." );
}
+ $lastTime = time();
do {
$job = ( $type === false )
? $group->pop( JobQueueGroup::TYPE_DEFAULT, JobQueueGroup::USE_CACHE )
break;
}
- // Don't let any slaves/backups fall behind...
+ // Don't let any queue slaves/backups fall behind
$group->get( $job->getType() )->waitForBackups();
+ // Don't let any of the main DB slaves get backed up
+ $timePassed = time() - $lastTime;
+ if ( $timePassed >= 5 || $timePassed < 0 ) {
+ wfWaitForSlaves();
+ }
}
} while ( $job ); // stop when there are no jobs
}
--- /dev/null
+<?php
+/**
+ * Show statistics from the cache.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once( __DIR__ . '/Maintenance.php' );
+
+/**
+ * Maintenance script that shows statistics from the cache.
+ *
+ * @ingroup Maintenance
+ */
+class ShowCacheStats extends Maintenance {
+
+ public function __construct() {
+ $this->mDescription = "Show statistics from the cache";
+ parent::__construct();
+ }
+
+ public function getDbType() {
+ return Maintenance::DB_NONE;
+ }
+
+ public function execute() {
+ global $wgMemc;
+
+ // Can't do stats if
+ if ( get_class( $wgMemc ) == 'EmptyBagOStuff' ) {
+ $this->error( "You are running EmptyBagOStuff, I can not provide any statistics.", true );
+ }
+ $session = intval( $wgMemc->get( wfMemcKey( 'stats', 'request_with_session' ) ) );
+ $noSession = intval( $wgMemc->get( wfMemcKey( 'stats', 'request_without_session' ) ) );
+ $total = $session + $noSession;
+ if ( $total == 0 ) {
+ $this->error( "You either have no stats or the cache isn't running. Aborting.", true );
+ }
+ $this->output( "Requests\n" );
+ $this->output( sprintf( "with session: %-10d %6.2f%%\n", $session, $session / $total * 100 ) );
+ $this->output( sprintf( "without session: %-10d %6.2f%%\n", $noSession, $noSession / $total * 100 ) );
+ $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ) );
+
+
+ $this->output( "\nParser cache\n" );
+ $hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_hit' ) ) );
+ $expired = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_expired' ) ) );
+ $absent = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_absent' ) ) );
+ $stub = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_stub' ) ) );
+ $total = $hits + $expired + $absent + $stub;
+ if ( $total ) {
+ $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits / $total * 100 ) );
+ $this->output( sprintf( "expired: %-10d %6.2f%%\n", $expired, $expired / $total * 100 ) );
+ $this->output( sprintf( "absent: %-10d %6.2f%%\n", $absent, $absent / $total * 100 ) );
+ $this->output( sprintf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub / $total * 100 ) );
+ $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ) );
+ } else {
+ $this->output( "no statistics available\n" );
+ }
+
+ $this->output( "\nImage cache\n" );
+ $hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'image_cache_hit' ) ) );
+ $misses = intval( $wgMemc->get( wfMemcKey( 'stats', 'image_cache_miss' ) ) );
+ $updates = intval( $wgMemc->get( wfMemcKey( 'stats', 'image_cache_update' ) ) );
+ $total = $hits + $misses;
+ if ( $total ) {
+ $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits / $total * 100 ) );
+ $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses / $total * 100 ) );
+ $this->output( sprintf( "updates: %-10d\n", $updates ) );
+ } else {
+ $this->output( "no statistics available\n" );
+ }
+
+ $this->output( "\nDiff cache\n" );
+ $hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'diff_cache_hit' ) ) );
+ $misses = intval( $wgMemc->get( wfMemcKey( 'stats', 'diff_cache_miss' ) ) );
+ $uncacheable = intval( $wgMemc->get( wfMemcKey( 'stats', 'diff_uncacheable' ) ) );
+ $total = $hits + $misses + $uncacheable;
+ if ( $total ) {
+ $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits / $total * 100 ) );
+ $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses / $total * 100 ) );
+ $this->output( sprintf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable / $total * 100 ) );
+ } else {
+ $this->output( "no statistics available\n" );
+ }
+ }
+}
+
+$maintClass = "ShowCacheStats";
+require_once( RUN_MAINTENANCE_IF_MAIN );
--- /dev/null
+<?php
+
+/**
+ * Show the cached statistics.
+ * Give out the same output as [[Special:Statistics]]
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ * @author Antoine Musso <hashar at free dot fr>
+ * Based on initSiteStats.php by:
+ * @author Brion Vibber
+ * @author Rob Church <robchur@gmail.com>
+ *
+ * @license GNU General Public License 2.0 or later
+ */
+
+require_once( __DIR__ . '/Maintenance.php' );
+
+/**
+ * Maintenance script to show the cached statistics.
+ *
+ * @ingroup Maintenance
+ */
+class ShowSiteStats extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Show the cached statistics";
+ }
+ public function execute() {
+ $fields = array(
+ 'ss_total_views' => 'Total views',
+ 'ss_total_edits' => 'Total edits',
+ 'ss_good_articles' => 'Number of articles',
+ 'ss_total_pages' => 'Total pages',
+ 'ss_users' => 'Number of users',
+ 'ss_images' => 'Number of images',
+ );
+
+ // Get cached stats from slave database
+ $dbr = wfGetDB( DB_SLAVE );
+ $stats = $dbr->selectRow( 'site_stats', '*', '', __METHOD__ );
+
+ // Get maximum size for each column
+ $max_length_value = $max_length_desc = 0;
+ foreach ( $fields as $field => $desc ) {
+ $max_length_value = max( $max_length_value, strlen( $stats->$field ) );
+ $max_length_desc = max( $max_length_desc, strlen( $desc ) ) ;
+ }
+
+ // Show them
+ foreach ( $fields as $field => $desc ) {
+ $this->output( sprintf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ) );
+ }
+ }
+}
+
+$maintClass = "ShowSiteStats";
+require_once( RUN_MAINTENANCE_IF_MAIN );
+++ /dev/null
-<?php
-
-/**
- * Show the cached statistics.
- * Give out the same output as [[Special:Statistics]]
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Antoine Musso <hashar at free dot fr>
- * Based on initStats.php by:
- * @author Brion Vibber
- * @author Rob Church <robchur@gmail.com>
- *
- * @license GNU General Public License 2.0 or later
- */
-
-require_once( __DIR__ . '/Maintenance.php' );
-
-/**
- * Maintenance script to show the cached statistics.
- *
- * @ingroup Maintenance
- */
-class ShowStats extends Maintenance {
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Show the cached statistics";
- }
- public function execute() {
- $fields = array(
- 'ss_total_views' => 'Total views',
- 'ss_total_edits' => 'Total edits',
- 'ss_good_articles' => 'Number of articles',
- 'ss_total_pages' => 'Total pages',
- 'ss_users' => 'Number of users',
- 'ss_images' => 'Number of images',
- );
-
- // Get cached stats from slave database
- $dbr = wfGetDB( DB_SLAVE );
- $stats = $dbr->selectRow( 'site_stats', '*', '', __METHOD__ );
-
- // Get maximum size for each column
- $max_length_value = $max_length_desc = 0;
- foreach ( $fields as $field => $desc ) {
- $max_length_value = max( $max_length_value, strlen( $stats->$field ) );
- $max_length_desc = max( $max_length_desc, strlen( $desc ) ) ;
- }
-
- // Show them
- foreach ( $fields as $field => $desc ) {
- $this->output( sprintf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ) );
- }
- }
-}
-
-$maintClass = "ShowStats";
-require_once( RUN_MAINTENANCE_IF_MAIN );
+++ /dev/null
-<?php
-/**
- * Show statistics from the cache.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- */
-
-require_once( __DIR__ . '/Maintenance.php' );
-
-/**
- * Maintenance script that shows statistics from the cache.
- *
- * @ingroup Maintenance
- */
-class CacheStats extends Maintenance {
-
- public function __construct() {
- $this->mDescription = "Show statistics from the cache";
- parent::__construct();
- }
-
- public function getDbType() {
- return Maintenance::DB_NONE;
- }
-
- public function execute() {
- global $wgMemc;
-
- // Can't do stats if
- if ( get_class( $wgMemc ) == 'EmptyBagOStuff' ) {
- $this->error( "You are running EmptyBagOStuff, I can not provide any statistics.", true );
- }
- $session = intval( $wgMemc->get( wfMemcKey( 'stats', 'request_with_session' ) ) );
- $noSession = intval( $wgMemc->get( wfMemcKey( 'stats', 'request_without_session' ) ) );
- $total = $session + $noSession;
- if ( $total == 0 ) {
- $this->error( "You either have no stats or the cache isn't running. Aborting.", true );
- }
- $this->output( "Requests\n" );
- $this->output( sprintf( "with session: %-10d %6.2f%%\n", $session, $session / $total * 100 ) );
- $this->output( sprintf( "without session: %-10d %6.2f%%\n", $noSession, $noSession / $total * 100 ) );
- $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ) );
-
-
- $this->output( "\nParser cache\n" );
- $hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_hit' ) ) );
- $expired = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_expired' ) ) );
- $absent = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_absent' ) ) );
- $stub = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_stub' ) ) );
- $total = $hits + $expired + $absent + $stub;
- if ( $total ) {
- $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits / $total * 100 ) );
- $this->output( sprintf( "expired: %-10d %6.2f%%\n", $expired, $expired / $total * 100 ) );
- $this->output( sprintf( "absent: %-10d %6.2f%%\n", $absent, $absent / $total * 100 ) );
- $this->output( sprintf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub / $total * 100 ) );
- $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ) );
- } else {
- $this->output( "no statistics available\n" );
- }
-
- $this->output( "\nImage cache\n" );
- $hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'image_cache_hit' ) ) );
- $misses = intval( $wgMemc->get( wfMemcKey( 'stats', 'image_cache_miss' ) ) );
- $updates = intval( $wgMemc->get( wfMemcKey( 'stats', 'image_cache_update' ) ) );
- $total = $hits + $misses;
- if ( $total ) {
- $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits / $total * 100 ) );
- $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses / $total * 100 ) );
- $this->output( sprintf( "updates: %-10d\n", $updates ) );
- } else {
- $this->output( "no statistics available\n" );
- }
-
- $this->output( "\nDiff cache\n" );
- $hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'diff_cache_hit' ) ) );
- $misses = intval( $wgMemc->get( wfMemcKey( 'stats', 'diff_cache_miss' ) ) );
- $uncacheable = intval( $wgMemc->get( wfMemcKey( 'stats', 'diff_uncacheable' ) ) );
- $total = $hits + $misses + $uncacheable;
- if ( $total ) {
- $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits / $total * 100 ) );
- $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses / $total * 100 ) );
- $this->output( sprintf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable / $total * 100 ) );
- } else {
- $this->output( "no statistics available\n" );
- }
- }
-}
-
-$maintClass = "CacheStats";
-require_once( RUN_MAINTENANCE_IF_MAIN );
*
* Write the new URL to the text table and set the bt_moved flag.
*
- * This is done in a single transaction to provide restartable behaviour
+ * This is done in a single transaction to provide restartable behavior
* without data loss.
*
* The transaction is kept short to reduce locking.
}
if ( $this->hasOption( 'postime' ) ) {
$id = (int)$src->getJournal()->getPositionAtTime( $this->getOption( 'postime' ) );
+ $this->output( "Requested journal position is $id.\n" );
} else {
$id = (int)$src->getJournal()->getCurrentPosition();
+ $this->output( "Current journal position is $id.\n" );
}
- $this->output( "Current journal position is $id.\n" );
if ( file_put_contents( $posFile, $id, LOCK_EX ) !== false ) {
$this->output( "Saved journal position file.\n" );
} else {
return array(
- /* Special modules who have their own classes */
+ /**
+ * Special modules who have their own classes
+ */
// Scripts managed by the local wiki (stored in the MediaWiki namespace)
'site' => array( 'class' => 'ResourceLoaderSiteModule' ),
// Scripts for the dynamic language specific data, like grammar forms.
'mediawiki.language.data' => array( 'class' => 'ResourceLoaderLanguageDataModule' ),
- /* Skins */
+ /**
+ * Skins
+ * Be careful not to add 'scripts' to these modules,
+ * since they are loaded with OutputPage::addModuleStyles so that the skin styles
+ * apply without javascript.
+ * If a skin needs custom js in the interface, register a separate module
+ * and add it to the load queue with OutputPage::addModules.
+ *
+ * See Vector for an example.
+ */
'skins.chick' => array(
'styles' => array( 'chick/main.css' => array( 'media' => 'screen, handheld' ) ),
'vector/screen.css' => array( 'media' => 'screen' ),
'vector/screen-hd.css' => array( 'media' => 'screen and (min-width: 982px)' ),
),
+ 'remoteBasePath' => $GLOBALS['wgStylePath'],
+ 'localBasePath' => $GLOBALS['wgStyleDirectory'],
+ ),
+ 'skins.vector.js' => array(
'scripts' => 'vector/vector.js',
'remoteBasePath' => $GLOBALS['wgStylePath'],
'localBasePath' => $GLOBALS['wgStyleDirectory'],
'scripts' => 'resources/mediawiki.api/mediawiki.api.parse.js',
'dependencies' => 'mediawiki.api',
),
- 'mediawiki.api.titleblacklist' => array(
- 'scripts' => 'resources/mediawiki.api/mediawiki.api.titleblacklist.js',
- 'dependencies' => array(
- 'mediawiki.api',
- 'mediawiki.Title',
- ),
- ),
'mediawiki.api.watch' => array(
'scripts' => 'resources/mediawiki.api/mediawiki.api.watch.js',
'dependencies' => array(
+++ /dev/null
-/**
- * @class mw.Api.plugin.titleblacklist
- */
-( function ( mw, $ ) {
-
- $.extend( mw.Api.prototype, {
- /**
- * Convinience method for `action=titleblacklist`.
- * Note: This action is not provided by MediaWiki core, but as part of the TitleBlacklist extension.
- *
- * @param {mw.Title|string} title
- * @param {Function} [ok] Success callback (deprecated)
- * @param {Function} [err] Error callback (deprecated)
- * @return {jQuery.Promise}
- * @return {Function} return.done
- * @return {Object|boolean} return.done.result False if title wasn't blacklisted, an object with 'reason', 'line'
- * and 'message' properties if title was blacklisted.
- */
- isBlacklisted: function ( title, ok, err ) {
- var d = $.Deferred();
- // Backwards compatibility (< MW 1.20)
- d.done( ok );
- d.fail( err );
-
- this.get( {
- action: 'titleblacklist',
- tbaction: 'create',
- tbtitle: title.toString()
- } )
- .done( function ( data ) {
- var result;
-
- // this fails open (if nothing valid is returned by the api, allows the title)
- // also fails open when the API is not present, which will be most of the time
- // as this API module is part of the TitleBlacklist extension.
- if ( data.titleblacklist && data.titleblacklist.result && data.titleblacklist.result === 'blacklisted' ) {
- if ( data.titleblacklist.reason ) {
- result = {
- reason: data.titleblacklist.reason,
- line: data.titleblacklist.line,
- message: data.titleblacklist.message
- };
- } else {
- mw.log( 'mw.Api.titleblacklist::isBlacklisted> no reason data for blacklisted title', 'debug' );
- result = {
- reason: 'Blacklisted, but no reason supplied',
- line: 'Unknown',
- message: null
- };
- }
- d.resolve( result );
- } else {
- d.resolve( false );
- }
- } )
- .fail( d.reject );
-
- return d.promise();
- }
-
- } );
-
- /**
- * @class mw.Api
- * @mixins mw.Api.plugin.titleblacklist
- */
-
-}( mediaWiki, jQuery ) );
// If the jQuery selector isn't found within the <ul>,
// or if nextnode was invalid or not passed at all,
- // then just append it at the end of the <ul> (this is the default behaviour)
+ // then just append it at the end of the <ul> (this is the default behavior)
} else {
$ul.append( $item );
}
"/{$this->stylename}/csshover{$min}.htc\")}</style><![endif]-->"
);
- $out->addModuleScripts( 'skins.vector' );
+ $out->addModules( 'skins.vector.js' );
}
/**
pre, code, tt, kbd, samp, .mw-code {
/*
* Some browsers will render the monospace text too small, namely Firefox, Chrome and Safari.
- * Specifying any valid, second value will trigger correct behaviour without forcing a different font.
+ * Specifying any valid, second value will trigger correct behavior without forcing a different font.
*/
font-family: monospace, Courier;
}
# PHPUnit 3.5.0 introduced a nice autoloader based on class name
require_once( 'PHPUnit/Autoload.php' );
} else {
- # Keep the old pre PHPUnit 3.5.0 behaviour for compatibility
+ # Keep the old pre PHPUnit 3.5.0 behavior for compatibility
require_once( 'PHPUnit/TextUI/Command.php' );
}
!!end
!! test
-Short headings with trailing space should match behaviour of Parser::doHeadings (bug 19910)
+Short headings with trailing space should match behavior of Parser::doHeadings (bug 19910)
!! input
===
The line above must have a trailing space!
==marked==
!!end
-# Test behaviour of bug 19910
+# Test behavior of bug 19910
!! test
Sectiion with all-equals
!! options
}
public function testUpdate_categorylinks() {
+ $this->setMwGlobals( 'wgCategoryCollation', 'uppercase' );
+
list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
$po->addCategory( "Foo", "FOO" );
--- /dev/null
+<?php
+
+/**
+ * @group Database
+ * @group Cache
+ */
+class MessageCacheTest extends MediaWikiLangTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+ MessageCache::singleton()->enable();
+ }
+
+ function addDBData() {
+ // Set up messages and fallbacks ab -> ru -> en
+ $this->makePage( 'FallbackLanguageTest-Full', 'ab' );
+ $this->makePage( 'FallbackLanguageTest-Full', 'ru' );
+ $this->makePage( 'FallbackLanguageTest-Full', 'en' );
+
+ // Fallbacks where ab does not exist
+ $this->makePage( 'FallbackLanguageTest-Partial', 'ru' );
+ $this->makePage( 'FallbackLanguageTest-Partial', 'en' );
+
+ // Fallback to english
+ $this->makePage( 'FallbackLanguageTest-English', 'en' );
+
+ // Full key tests -- always want russian
+ $this->makePage( 'MessageCacheTest-FullKeyTest', 'ab' );
+ $this->makePage( 'MessageCacheTest-FullKeyTest', 'ru' );
+ }
+
+ /**
+ * Helper function for addDBData -- adds a simple page to the database
+ *
+ * @param string $title Title of page to be created
+ * @param string $lang Language and content of the created page
+ */
+ protected function makePage( $title, $lang ) {
+ global $wgContLang;
+
+ $title = Title::newFromText(
+ ($lang == $wgContLang->getCode()) ? $title : "$title/$lang",
+ NS_MEDIAWIKI
+ );
+ $wikiPage = new WikiPage( $title );
+ $content = ContentHandler::makeContent( $lang, $title );
+ $wikiPage->doEditContent( $content, "$lang translation test case" );
+ }
+
+ /**
+ * Test message fallbacks, bug #1495
+ *
+ * @dataProvider provideMessagesForFallback
+ */
+ function testMessageFallbacks( $message, $lang, $expectedContent ) {
+ $result = MessageCache::singleton()->get( $message, true, $lang );
+ $this->assertEquals( $expectedContent, $result, "Message fallback failed." );
+ }
+
+ function provideMessagesForFallback() {
+ return array(
+ array( 'FallbackLanguageTest-Full', 'ab', 'ab' ),
+ array( 'FallbackLanguageTest-Partial', 'ab', 'ru' ),
+ array( 'FallbackLanguageTest-English', 'ab', 'en' ),
+ array( 'FallbackLanguageTest-None', 'ab', false ),
+ );
+ }
+
+ /**
+ * There's a fallback case where the message key is given as fully qualified -- this
+ * should ignore the passed $lang and use the language from the key
+ *
+ * @dataProvider provideMessagesForFullKeys
+ */
+ function testFullKeyBehaviour( $message, $lang, $expectedContent ) {
+ $result = MessageCache::singleton()->get( $message, true, $lang, true );
+ $this->assertEquals( $expectedContent, $result, "Full key message fallback failed." );
+ }
+
+ function provideMessagesForFullKeys() {
+ return array(
+ array( 'MessageCacheTest-FullKeyTest/ru', 'ru', 'ru' ),
+ array( 'MessageCacheTest-FullKeyTest/ru', 'ab', 'ru' ),
+ array( 'MessageCacheTest-FullKeyTest/ru/foo', 'ru', false ),
+ );
+ }
+
+}
);
}
+ /**
+ * @since 1.21
+ * @return array
+ */
+ protected function getMockValues() {
+ return array(
+ 'id' => 1,
+ 'str' => 'foobar4645645',
+ 'int' => 42,
+ 'float' => 4.2,
+ 'bool' => '',
+ 'array' => array( 42, 'foobar' ),
+ 'blob' => new stdClass()
+ );
+ }
+
}
class TestORMRow extends ORMRow {}
'#settings td p strong'
),
array(
- // Test the colors regex
- '.foo { border-color: red green blue white }',
- '.foo { border-color: red white blue green }',
+ # Not sure how 4+ values should behave,
+ # testing to make sure changes are detected
+ '.foo { x-unknown: 1 2 3 4 5; }',
+ '.foo { x-unknown: 1 4 3 2 5; }',
),
array(
- // Test the colors regex harder
- '.foo { border-color: red #f00 rgb(255, 0, 0%) rgba(100%, 0, 0, 0) }',
- '.foo { border-color: red rgba(100%, 0, 0, 0) rgb(255, 0, 0%) #f00 }',
- ),
- array(
- // Do not bork 4+ values
- '.foo { x-unknown: 1 2 3 4 5; }'
- ),
- array(
- '.foo { x-unknown: 1 2 3 4 5 6; }'
+ '.foo { x-unknown: 1 2 3 4 5 6; }',
+ '.foo { x-unknown: 1 4 3 2 5 6; }',
),
// Shorthand / Three notation
'.foo { padding: 1px; }'
),
- // text-shadow and box-shadow
- array(
- '.foo { box-shadow: -6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
- '.foo { box-shadow: 6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
- ),
- array(
- '.foo { box-shadow: inset -6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
- '.foo { box-shadow: inset 6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
- ),
- array(
- '.foo { text-shadow: orange 2px 0; }',
- '.foo { text-shadow: orange -2px 0; }',
- ),
- array(
- '.foo { text-shadow: 2px 0 orange; }',
- '.foo { text-shadow: -2px 0 orange; }',
- ),
- array(
- // Don't mangle zeroes
- '.foo { text-shadow: orange 0 2px; }'
- ),
-
// Direction
// Note: This differs from the Python implementation,
// see also CSSJanus::fixDirection for more info.
$name = $this->getCliArg( 'use-bagostuff=' );
$this->cache = ObjectCache::newFromId( $name );
+
} else {
// no type defined - use simple hash
$this->cache = new HashBagOStuff;
}
}
}
+
+ public function testAdd() {
+ $key = wfMemcKey( 'test' );
+ $this->assertTrue( $this->cache->add( $key, 'test' ) );
+ }
+
+ public function testGet() {
+ $value = array( 'this' => 'is', 'a' => 'test' );
+
+ $key = wfMemcKey( 'test' );
+ $this->cache->add( $key, $value );
+ $this->assertEquals( $this->cache->get( $key ), $value );
+ }
+
+ public function testGetMulti() {
+ $value1 = array( 'this' => 'is', 'a' => 'test' );
+ $value2 = array( 'this' => 'is', 'another' => 'test' );
+
+ $key1 = wfMemcKey( 'test1' );
+ $key2 = wfMemcKey( 'test2' );
+
+ $this->cache->add( $key1, $value1 );
+ $this->cache->add( $key2, $value2 );
+
+ $this->assertEquals( $this->cache->getMulti( array( $key1, $key2 ) ), array( $key1 => $value1, $key2 => $value2 ) );
+
+ // cleanup
+ $this->cache->delete( $key1 );
+ $this->cache->delete( $key2 );
+ }
}
// Someone generated a MaintenanceFixup instance without calling
// simulateShutdown. We'd have to raise a PHPUnit exception to correctly
// flag this illegal usage. However, we are already in a destruktor, which
- // would trigger undefined behaviour. Hence, we can only report to the
+ // would trigger undefined behavior. Hence, we can only report to the
// error output :( Hopefully people read the PHPUnit output.
$name = $this->testCase->getName();
fwrite( STDERR, "ERROR! Instance of " . __CLASS__ . " for test $name "
// Although the following tests do not seem to be too consistent (compare for
// example the newlines within the test.*StringString tests, or the
// test.*Intermittent.* tests), the objective of these tests is not to describe
- // consistent behaviour, but rather currently existing behaviour.
+ // consistent behavior, but rather currently existing behavior.
function testOutputEmpty() {
assert.deepEqual( $.colorUtil.getRGB( '#eEe' ), [238, 238, 238], 'Hex string: 3 char mixed' );
assert.deepEqual( $.colorUtil.getRGB( 'rgba(0, 0, 0, 0)' ), [255, 255, 255], 'Zero rgba for Safari 3; Transparent (whitespace)' );
- // Perhaps this is a bug in colorUtil, but it is the current behaviour so, let's keep
+ // Perhaps this is a bug in colorUtil, but it is the current behavior so, let's keep
// track of it, so we will know in case it would ever change.
assert.strictEqual( $.colorUtil.getRGB( 'rgba(0,0,0,0)' ), undefined, 'Zero rgba without whitespace' );
assert.strictEqual( $.isEmpty( [] ), true, 'isEmpty: []' );
assert.strictEqual( $.isEmpty( {} ), true, 'isEmpty: {}' );
- // Documented behaviour
+ // Documented behavior
assert.strictEqual( $.isEmpty( { length: 0 } ), true, 'isEmpty: { length: 0 }' );
} );