diff options
Diffstat (limited to 'maintenance')
147 files changed, 1944 insertions, 771 deletions
diff --git a/maintenance/FiveUpgrade.inc b/maintenance/FiveUpgrade.inc index c32f1b2e..9a882bc6 100644 --- a/maintenance/FiveUpgrade.inc +++ b/maintenance/FiveUpgrade.inc @@ -693,10 +693,7 @@ END; return $copy; } - function imageInfo( $name, $subdirCallback='wfImageDir', $basename = null ) { - if( is_null( $basename ) ) $basename = $name; - $dir = call_user_func( $subdirCallback, $basename ); - $filename = $dir . '/' . $name; + function imageInfo( $filename ) { $info = array( 'width' => 0, 'height' => 0, @@ -711,20 +708,13 @@ END; $info['media'] = $magic->getMediaType( $filename, $mime ); - # Height and width - $gis = false; - if( $mime == 'image/svg' ) { - $gis = wfGetSVGsize( $filename ); - } elseif( $magic->isPHPImageType( $mime ) ) { - $gis = getimagesize( $filename ); - } else { - $this->log( "Surprising mime type: $mime" ); - } - if( $gis ) { - $info['width' ] = $gis[0]; - $info['height'] = $gis[1]; - } - if( isset( $gis['bits'] ) ) { + $image = UnregisteredLocalFile::newFromPath( $filename, $mime ); + + $info['width'] = $image->getWidth(); + $info['height'] = $image->getHeight(); + + $gis = $image->getImageSize(); + if ( isset( $gis['bits'] ) ) { $info['bits'] = $gis['bits']; } @@ -896,7 +886,7 @@ END; } function upgradeLogging() { - $tabledef = <<<END + $tabledef = <<<ENDS CREATE TABLE $1 ( -- Symbolic keys for the general log type and the action type -- within the log. The output format will be controlled by the @@ -926,7 +916,7 @@ CREATE TABLE $1 ( KEY page_time (log_namespace, log_title, log_timestamp) ) TYPE=InnoDB -END; +ENDS; $fields = array( 'log_type' => MW_UPGRADE_COPY, 'log_action' => MW_UPGRADE_COPY, @@ -940,7 +930,7 @@ END; } function upgradeArchive() { - $tabledef = <<<END + $tabledef = <<<ENDS CREATE TABLE $1 ( ar_namespace int NOT NULL default '0', ar_title varchar(255) binary NOT NULL default '', @@ -960,7 +950,7 @@ CREATE TABLE $1 ( KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp) ) TYPE=InnoDB -END; +ENDS; $fields = array( 'ar_namespace' => MW_UPGRADE_COPY, 'ar_title' => MW_UPGRADE_ENCODE, @@ -979,7 +969,7 @@ END; function upgradeImagelinks() { global $wgUseLatin1; if( $wgUseLatin1 ) { - $tabledef = <<<END + $tabledef = <<<ENDS CREATE TABLE $1 ( -- Key to page_id of the page containing the image / media link. il_from int(8) unsigned NOT NULL default '0', @@ -993,7 +983,7 @@ CREATE TABLE $1 ( KEY (il_to) ) TYPE=InnoDB -END; +ENDS; $fields = array( 'il_from' => MW_UPGRADE_COPY, 'il_to' => MW_UPGRADE_ENCODE ); @@ -1004,7 +994,7 @@ END; function upgradeCategorylinks() { global $wgUseLatin1; if( $wgUseLatin1 ) { - $tabledef = <<<END + $tabledef = <<<ENDS CREATE TABLE $1 ( cl_from int(8) unsigned NOT NULL default '0', cl_to varchar(255) binary NOT NULL default '', @@ -1015,7 +1005,7 @@ CREATE TABLE $1 ( KEY cl_sortkey(cl_to,cl_sortkey), KEY cl_timestamp(cl_to,cl_timestamp) ) TYPE=InnoDB -END; +ENDS; $fields = array( 'cl_from' => MW_UPGRADE_COPY, 'cl_to' => MW_UPGRADE_ENCODE, @@ -1028,7 +1018,7 @@ END; function upgradeIpblocks() { global $wgUseLatin1; if( $wgUseLatin1 ) { - $tabledef = <<<END + $tabledef = <<<ENDS CREATE TABLE $1 ( ipb_id int(8) NOT NULL auto_increment, ipb_address varchar(40) binary NOT NULL default '', @@ -1044,7 +1034,7 @@ CREATE TABLE $1 ( INDEX ipb_user (ipb_user) ) TYPE=InnoDB -END; +ENDS; $fields = array( 'ipb_id' => MW_UPGRADE_COPY, 'ipb_address' => MW_UPGRADE_COPY, @@ -1060,7 +1050,7 @@ END; function upgradeRecentchanges() { // There's a format change in the namespace field - $tabledef = <<<END + $tabledef = <<<ENDS CREATE TABLE $1 ( rc_id int(8) NOT NULL auto_increment, rc_timestamp varchar(14) binary NOT NULL default '', @@ -1098,7 +1088,7 @@ CREATE TABLE $1 ( INDEX rc_ip (rc_ip) ) TYPE=InnoDB -END; +ENDS; $fields = array( 'rc_id' => MW_UPGRADE_COPY, 'rc_timestamp' => MW_UPGRADE_COPY, @@ -1124,7 +1114,7 @@ END; function upgradeQuerycache() { // There's a format change in the namespace field - $tabledef = <<<END + $tabledef = <<<ENDS CREATE TABLE $1 ( -- A key name, generally the base name of of the special page. qc_type char(32) NOT NULL, @@ -1139,7 +1129,7 @@ CREATE TABLE $1 ( KEY (qc_type,qc_value) ) TYPE=InnoDB -END; +ENDS; $fields = array( 'qc_type' => MW_UPGRADE_COPY, 'qc_value' => MW_UPGRADE_COPY, diff --git a/maintenance/README b/maintenance/README index 9eb69ba8..7ef358b8 100644 --- a/maintenance/README +++ b/maintenance/README @@ -39,6 +39,9 @@ installations. cleanupSpam.php Mass-revert insertion of linkspam + createAndPromote.php + Create a user with administrator (and optionally, bureaucrat) permissions + deleteOldRevisions.php Erase old revisions of pages from the database @@ -52,10 +55,10 @@ installations. XML dump importer importImages.php - Imports images into the wiki + Import images into the wiki importTextFile.php - Imports the contents of a text file into a wiki page + Import the contents of a text file into a wiki page nukePage.php Wipe a page and all revisions from the database @@ -82,4 +85,4 @@ installations. Immediately complete all jobs in the job queue update.php - Check and upgrade the database schema to the current version
\ No newline at end of file + Check and upgrade the database schema to the current version diff --git a/maintenance/addwiki.php b/maintenance/addwiki.php index 642b1324..3b6bb5d6 100644 --- a/maintenance/addwiki.php +++ b/maintenance/addwiki.php @@ -233,4 +233,4 @@ See the [http://www.wikipedia.org Wikipedia portal] for other language Wikipedia print "Script ended. You now want to run sync-common-all to publish *dblist files (check them for duplicates first)\n"; } -?> + diff --git a/maintenance/archives/patch-archive-page_id.sql b/maintenance/archives/patch-archive-page_id.sql new file mode 100644 index 00000000..47a1c47e --- /dev/null +++ b/maintenance/archives/patch-archive-page_id.sql @@ -0,0 +1,6 @@ +-- Reference to page_id. Useful for sysadmin fixing of large +-- pages merged together in the archives +-- Added 2007-07-21 + +ALTER TABLE /*$wgDBprefix*/archive + ADD ar_page_id int unsigned; diff --git a/maintenance/archives/patch-archive-user-index.sql b/maintenance/archives/patch-archive-user-index.sql new file mode 100644 index 00000000..62baa2dd --- /dev/null +++ b/maintenance/archives/patch-archive-user-index.sql @@ -0,0 +1,4 @@ +-- Adds a user,timestamp index to the archive table +-- Used for browsing deleted contributions and renames +ALTER TABLE /*$wgDBprefix*/archive + ADD INDEX usertext_timestamp ( ar_user_text , ar_timestamp ); diff --git a/maintenance/archives/patch-categorylinksindex.sql b/maintenance/archives/patch-categorylinksindex.sql new file mode 100644 index 00000000..8a9ff123 --- /dev/null +++ b/maintenance/archives/patch-categorylinksindex.sql @@ -0,0 +1,11 @@ +-- +-- patch-categorylinksindex.sql +-- +-- Per bug 10280 / http://bugzilla.wikimedia.org/show_bug.cgi?id=10280 +-- +-- Improve enum continuation performance of the what pages belong to a category query +-- + +ALTER TABLE /*$wgDBprefix*/categorylinks + DROP INDEX cl_sortkey, + ADD INDEX cl_sortkey(cl_to, cl_sortkey, cl_from); diff --git a/maintenance/archives/patch-image-user-index.sql b/maintenance/archives/patch-image-user-index.sql new file mode 100644 index 00000000..db56b221 --- /dev/null +++ b/maintenance/archives/patch-image-user-index.sql @@ -0,0 +1,8 @@ +-- +-- image-user-index.sql +-- +-- Add user/timestamp index to current image versions +-- + +ALTER TABLE /*$wgDBprefix*/image + ADD INDEX img_usertext_timestamp (img_user_text,img_timestamp); diff --git a/maintenance/archives/patch-img_sha1.sql b/maintenance/archives/patch-img_sha1.sql new file mode 100644 index 00000000..35950f58 --- /dev/null +++ b/maintenance/archives/patch-img_sha1.sql @@ -0,0 +1,8 @@ +-- Add img_sha1, oi_sha1 and related indexes +ALTER TABLE /*$wgDBprefix*/image + ADD COLUMN img_sha1 varbinary(32) NOT NULL default '', + ADD INDEX img_sha1 (img_sha1); + +ALTER TABLE /*$wgDBprefix*/oldimage + ADD COLUMN oi_sha1 varbinary(32) NOT NULL default '', + ADD INDEX oi_sha1 (oi_sha1); diff --git a/maintenance/archives/patch-ipb_emailban.sql b/maintenance/archives/patch-ipb_emailban.sql new file mode 100644 index 00000000..e05c20b3 --- /dev/null +++ b/maintenance/archives/patch-ipb_emailban.sql @@ -0,0 +1,4 @@ +-- Add row for email blocks -- + +ALTER TABLE /*$wgDBprefix*/ipblocks + ADD ipb_block_email tinyint NOT NULL default '0'; diff --git a/maintenance/archives/patch-oi_metadata.sql b/maintenance/archives/patch-oi_metadata.sql new file mode 100644 index 00000000..bc848878 --- /dev/null +++ b/maintenance/archives/patch-oi_metadata.sql @@ -0,0 +1,17 @@ +-- +-- patch-oi_metadata.sql +-- +-- Add data to allow for direct reference to old images +-- Some re-indexing here. +-- Old images can be included into pages effeciently now. +-- + +ALTER TABLE /*$wgDBprefix*/oldimage + DROP INDEX oi_name, + ADD INDEX oi_name_timestamp (oi_name,oi_timestamp), + ADD INDEX oi_name_archive_name (oi_name,oi_archive_name(14)), + ADD oi_metadata mediumblob NOT NULL, + ADD oi_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL, + ADD oi_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown", + ADD oi_minor_mime varbinary(32) NOT NULL default "unknown", + ADD oi_deleted tinyint unsigned NOT NULL default '0'; diff --git a/maintenance/archives/patch-oldimage-user-index.sql b/maintenance/archives/patch-oldimage-user-index.sql new file mode 100644 index 00000000..949625eb --- /dev/null +++ b/maintenance/archives/patch-oldimage-user-index.sql @@ -0,0 +1,8 @@ +-- +-- oldimage-user-index.sql +-- +-- Add user/timestamp index to old image versions +-- + +ALTER TABLE /*$wgDBprefix*/oldimage + ADD INDEX oi_usertext_timestamp (oi_user_text,oi_timestamp); diff --git a/maintenance/archives/patch-page_restrictions.sql b/maintenance/archives/patch-page_restrictions.sql index c18a054e..6813c1e7 100644 --- a/maintenance/archives/patch-page_restrictions.sql +++ b/maintenance/archives/patch-page_restrictions.sql @@ -14,8 +14,6 @@ CREATE TABLE /*$wgDBprefix*/page_restrictions ( pr_expiry varbinary(14) NULL, PRIMARY KEY pr_pagetype (pr_page,pr_type), - - KEY pr_page (pr_page), KEY pr_typelevel (pr_type,pr_level), KEY pr_level (pr_level), KEY pr_cascade (pr_cascade) diff --git a/maintenance/archives/patch-rc_deleted.sql b/maintenance/archives/patch-rc_deleted.sql index cc668433..04ead974 100644 --- a/maintenance/archives/patch-rc_deleted.sql +++ b/maintenance/archives/patch-rc_deleted.sql @@ -5,4 +5,4 @@ ALTER TABLE /*$wgDBprefix*/recentchanges ADD rc_logid int unsigned NOT NULL default '0', ADD rc_log_type varbinary(255) NULL default NULL, ADD rc_log_action varbinary(255) NULL default NULL, - ADD rc_params blob NOT NULL default ''; + ADD rc_params BLOB NULL; diff --git a/maintenance/archives/populateSha1.php b/maintenance/archives/populateSha1.php new file mode 100644 index 00000000..a34d36d3 --- /dev/null +++ b/maintenance/archives/populateSha1.php @@ -0,0 +1,43 @@ +<?php + +# Optional upgrade script to populate the img_sha1 field + +$optionsWithArgs = array( 'method' ); +require_once( dirname(__FILE__).'/../commandLine.inc' ); +$method = isset( $args['method'] ) ? $args['method'] : 'normal'; + +$t = -microtime( true ); +$fname = 'populateSha1.php'; +$dbw = wfGetDB( DB_MASTER ); +$res = $dbw->select( 'image', array( 'img_name' ), array( 'img_sha1' => '' ), $fname ); +$imageTable = $dbw->tableName( 'image' ); +$oldimageTable = $dbw->tableName( 'oldimage' ); +$batch = array(); + +$cmd = 'mysql -u ' . wfEscapeShellArg( $wgDBuser ) . ' -p' . wfEscapeShellArg( $wgDBpassword, $wgDBname ); +if ( $method == 'pipe' ) { + $pipe = popen( $cmd, 'w' ); + fwrite( $pipe, "-- hello\n" ); +} + +foreach ( $res as $row ) { + $file = wfLocalFile( $row->img_name ); + $sha1 = File::sha1Base36( $file->getPath() ); + if ( strval( $sha1 ) !== '' ) { + $sql = "UPDATE $imageTable SET img_sha1=" . $dbw->addQuotes( $sha1 ) . + " WHERE img_name=" . $dbw->addQuotes( $row->img_name ); + if ( $method == 'pipe' ) { + fwrite( $pipe, $sql ); + } else { + $dbw->query( $sql, $fname ); + } + } +} +if ( $method == 'pipe' ) { + fflush( $pipe ); + pclose( $pipe ); +} +$t += microtime( true ); +print "Done in $t seconds\n"; + +?> diff --git a/maintenance/archives/upgradeWatchlist.php b/maintenance/archives/upgradeWatchlist.php index 250c6677..e62a39ad 100644 --- a/maintenance/archives/upgradeWatchlist.php +++ b/maintenance/archives/upgradeWatchlist.php @@ -63,4 +63,4 @@ $sql = "ALTER TABLE watchlist ADD INDEX wl_page (wl_page)"; #wfQuery( $sql, DB_MASTER ); -?> + diff --git a/maintenance/attachLatest.php b/maintenance/attachLatest.php index b24143ca..22cd7372 100644 --- a/maintenance/attachLatest.php +++ b/maintenance/attachLatest.php @@ -69,4 +69,4 @@ if( !$fixit ) { echo "This was a dry run; rerun with --fix to update page_latest.\n"; } -?> + diff --git a/maintenance/attribute.php b/maintenance/attribute.php index 4f575cba..999c0117 100644 --- a/maintenance/attribute.php +++ b/maintenance/attribute.php @@ -101,4 +101,4 @@ print "\n"; fclose( $sqlfile ); fclose( $logfile ); -?> + diff --git a/maintenance/benchmarkPurge.php b/maintenance/benchmarkPurge.php index bbe73b74..0ceb8445 100644 --- a/maintenance/benchmarkPurge.php +++ b/maintenance/benchmarkPurge.php @@ -61,4 +61,3 @@ if( !$wgUseSquid ) { print "$trial\n"; } } -?>
\ No newline at end of file diff --git a/maintenance/changePassword.php b/maintenance/changePassword.php index 82913411..d6121280 100644 --- a/maintenance/changePassword.php +++ b/maintenance/changePassword.php @@ -9,12 +9,37 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later */ +$optionsWithArgs = array( 'user', 'password' ); +require_once 'commandLine.inc'; + +$USAGE = + "Usage: php changePassword.php [--user=user --password=password | --help]\n" . + "\toptions:\n" . + "\t\t--help show this message\n" . + "\t\t--user the username to operate on\n" . + "\t\t--password the password to use\n"; + +if( in_array( '--help', $argv ) ) + wfDie( $USAGE ); + +$cp = new ChangePassword( @$options['user'], @$options['password'] ); +$cp->main(); + class ChangePassword { var $dbw; var $user, $password; function ChangePassword( $user, $password ) { + global $USAGE; + if( !strlen( $user ) or !strlen( $password ) ) { + wfDie( $USAGE ); + } + $this->user = User::newFromName( $user ); + if ( !$this->user->getID() ) { + die ( "No such user: $user\n" ); + } + $this->password = $password; $this->dbw = wfGetDB( DB_MASTER ); @@ -35,18 +60,4 @@ class ChangePassword { } } -$optionsWithArgs = array( 'user', 'password' ); -require_once 'commandLine.inc'; - -if( in_array( '--help', $argv ) ) - wfDie( - "Usage: php changePassword.php [--user=user --password=password | --help]\n" . - "\toptions:\n" . - "\t\t--help\tshow this message\n" . - "\t\t--user\tthe username to operate on\n" . - "\t\t--password\tthe password to use\n" - ); -$cp = new ChangePassword( @$options['user'], @$options['password'] ); -$cp->main(); -?> diff --git a/maintenance/checkUsernames.php b/maintenance/checkUsernames.php index cfff3468..3441aeeb 100644 --- a/maintenance/checkUsernames.php +++ b/maintenance/checkUsernames.php @@ -31,4 +31,4 @@ class checkUsernames { $cun = new checkUsernames(); $cun->main(); -?> + diff --git a/maintenance/cleanupCaps.php b/maintenance/cleanupCaps.php index 5a61bf23..77a95ffa 100644 --- a/maintenance/cleanupCaps.php +++ b/maintenance/cleanupCaps.php @@ -153,4 +153,4 @@ $ns = isset( $options['namespace'] ) ? $options['namespace'] : 0; $caps = new CapsCleanup( isset( $options['dry-run'] ), $ns ); $caps->cleanup(); -?> + diff --git a/maintenance/cleanupImages.php b/maintenance/cleanupImages.php index 3ec2c443..1c0edeb5 100644 --- a/maintenance/cleanupImages.php +++ b/maintenance/cleanupImages.php @@ -89,7 +89,10 @@ class ImageCleanup extends TableCleanup { } function filePath( $name ) { - return wfImageDir( $name ) . "/$name"; + if ( !isset( $this->repo ) ) { + $this->repo = RepoGroup::singleton()->getLocalRepo(); + } + return $this->repo->getRootDirectory() . '/' . $this->repo->getHashPath( $name ) . $name; } function pokeFile( $orig, $new ) { @@ -164,4 +167,4 @@ $wgUser->setName( 'Conversion script' ); $caps = new ImageCleanup( !isset( $options['fix'] ) ); $caps->cleanup(); -?> + diff --git a/maintenance/cleanupSpam.php b/maintenance/cleanupSpam.php index 534e160d..2c269b34 100644 --- a/maintenance/cleanupSpam.php +++ b/maintenance/cleanupSpam.php @@ -108,4 +108,4 @@ if ( isset($options['all']) ) { } } -?> + diff --git a/maintenance/cleanupTitles.php b/maintenance/cleanupTitles.php index 0fb97c6e..0ec57d4e 100644 --- a/maintenance/cleanupTitles.php +++ b/maintenance/cleanupTitles.php @@ -135,4 +135,4 @@ $wgUser->setName( 'Conversion script' ); $caps = new TitleCleanup( !isset( $options['fix'] ) ); $caps->cleanup(); -?> + diff --git a/maintenance/cleanupWatchlist.php b/maintenance/cleanupWatchlist.php index 161a9846..bcf05730 100644 --- a/maintenance/cleanupWatchlist.php +++ b/maintenance/cleanupWatchlist.php @@ -134,4 +134,4 @@ $wgUser->setName( 'Conversion script' ); $caps = new WatchlistCleanup( !isset( $options['fix'] ) ); $caps->cleanup(); -?> + diff --git a/maintenance/clear_interwiki_cache.php b/maintenance/clear_interwiki_cache.php index 6f4cfe17..af5d9b2f 100644 --- a/maintenance/clear_interwiki_cache.php +++ b/maintenance/clear_interwiki_cache.php @@ -22,4 +22,4 @@ foreach ( $wgLocalDatabases as $db ) { } } print "\n"; -?> + diff --git a/maintenance/clear_stats.php b/maintenance/clear_stats.php index 00cfd0ce..5c1dce97 100644 --- a/maintenance/clear_stats.php +++ b/maintenance/clear_stats.php @@ -28,4 +28,4 @@ function noisyDelete( $key ) { }*/ $wgMemc->delete($key); } -?> + diff --git a/maintenance/commandLine.inc b/maintenance/commandLine.inc index 3bf7f1b2..4466344f 100644 --- a/maintenance/commandLine.inc +++ b/maintenance/commandLine.inc @@ -34,6 +34,7 @@ if ( !isset( $optionsWithArgs ) ) { $optionsWithArgs = array(); } $optionsWithArgs[] = 'conf'; # For specifying the location of LocalSettings.php +$optionsWithArgs[] = 'aconf'; # As above for AdminSettings.php $self = array_shift( $argv ); $IP = realpath( dirname( __FILE__ ) . '/..' ); @@ -179,11 +180,14 @@ if ( file_exists( '/home/wikipedia/common/langlist' ) ) { #require_once( $IP.'/includes/ProfilerStub.php' ); require_once( $IP.'/includes/Defines.php' ); require_once( $settingsFile ); - ini_set( 'include_path', ".$sep$IP$sep$IP/includes$sep$IP/languages$sep$IP/maintenance" ); + /* ini_set( 'include_path', ".$sep$IP$sep$IP/includes$sep$IP/languages$sep$IP/maintenance" ); */ + + $adminSettings = isset( $options['aconf'] ) + ? $options['aconf'] + : "{$IP}/AdminSettings.php"; + if( is_readable( $adminSettings ) ) + require_once( $adminSettings ); - if ( is_readable( $IP.'/AdminSettings.php' ) ) { - require_once( $IP.'/AdminSettings.php' ); - } } # Turn off output buffering again, it might have been turned on in the settings files @@ -214,8 +218,8 @@ ini_set( 'memory_limit', -1 ); $wgShowSQLErrors = true; -require_once( 'Setup.php' ); -require_once( 'install-utils.inc' ); +require_once( "$IP/includes/Setup.php" ); +require_once( "$IP/install-utils.inc" ); $wgTitle = null; # Much much faster startup than creating a title object set_time_limit(0); diff --git a/maintenance/convertLinks.php b/maintenance/convertLinks.php index 6d07df50..bc0aef49 100644 --- a/maintenance/convertLinks.php +++ b/maintenance/convertLinks.php @@ -12,4 +12,4 @@ require_once( "convertLinks.inc" ); convertLinks(); -?> + diff --git a/maintenance/counter.php b/maintenance/counter.php index d84c877d..67b9ce21 100644 --- a/maintenance/counter.php +++ b/maintenance/counter.php @@ -2,4 +2,4 @@ function print_c($last, $current) { echo str_repeat( chr(8), strlen( $last ) ) . $current; } -?> + diff --git a/maintenance/createAndPromote.php b/maintenance/createAndPromote.php index 7ef48e08..af4a1dab 100644 --- a/maintenance/createAndPromote.php +++ b/maintenance/createAndPromote.php @@ -6,10 +6,16 @@ * @addtogroup Maintenance * @author Rob Church <robchur@gmail.com> */ - + +$options = array( 'help', 'bureaucrat' ); require_once( 'commandLine.inc' ); -if( !count( $args ) == 2 ) { +if( isset( $options['help'] ) ) { + showHelp(); + exit( 1 ); +} + +if( count( $args ) < 2 ) { echo( "Please provide a username and password for the new account.\n" ); die( 1 ); } @@ -36,6 +42,8 @@ $user->setToken(); # Promote user $user->addGroup( 'sysop' ); +if( isset( $option['bureaucrat'] ) ) + $user->addGroup( 'bureaucrat' ); # Increment site_stats.ss_users $ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 ); @@ -43,4 +51,17 @@ $ssu->doUpdate(); echo( "done.\n" ); -?> +function showHelp() { + echo( <<<EOT +Create a new user account with administrator rights + +USAGE: php createAndPromote.php [--bureaucrat|--help] <username> <password> + + --bureaucrat + Grant the account bureaucrat rights + --help + Show this help information + +EOT + ); +}
\ No newline at end of file diff --git a/maintenance/deleteArchivedFiles.inc b/maintenance/deleteArchivedFiles.inc new file mode 100644 index 00000000..32ddf4c8 --- /dev/null +++ b/maintenance/deleteArchivedFiles.inc @@ -0,0 +1,56 @@ +<?php + +/** + * Support functions for the deleteArchivedFiles script + * + * @addtogroup Maintenance + * @author Aaron Schulz + */ + +require_once( "$IP/includes/FileStore.php" ); + +function DeleteArchivedFiles( $delete = false ) { + + # Data should come off the master, wrapped in a transaction + $dbw = wfGetDB( DB_MASTER ); + $dbw->begin(); + + $transaction = new FSTransaction(); + if( !FileStore::lock() ) { + wfDebug( __METHOD__.": failed to acquire file store lock, aborting\n" ); + return false; + } + + $tbl_arch = $dbw->tableName( 'filearchive' ); + + # Get "active" revisions from the filearchive table + echo( "Searching for and deleting archived files...\n" ); + $res = $dbw->query( "SELECT fa_id,fa_storage_group,fa_storage_key FROM $tbl_arch" ); + while( $row = $dbw->fetchObject( $res ) ) { + $key = $row->fa_storage_key; + $group = $row->fa_storage_group; + $id = $row->fa_id; + + $store = FileStore::get( $group ); + if ( $store ) { + $path = $store->filePath( $key ); + if ( $path && file_exists($path) ) { + $transaction->addCommit( FSTransaction::DELETE_FILE, $path ); + $dbw->query( "DELETE FROM $tbl_arch WHERE fa_id = $id" ); + } else { + echo( "Notice - file '$key' not found in group '$group'\n" ); + } + } else { + echo( "Notice - invalid file storage group '$group'\n" ); + } + } + echo( "done.\n" ); + + $transaction->commit(); + + # This bit's done + $dbw->commit(); + +} + +?>
\ No newline at end of file diff --git a/maintenance/deleteArchivedFiles.php b/maintenance/deleteArchivedFiles.php new file mode 100644 index 00000000..a556c3b9 --- /dev/null +++ b/maintenance/deleteArchivedFiles.php @@ -0,0 +1,30 @@ +<?php + +/** + * Delete archived (non-current) files from the database + * + * @addtogroup Maintenance + * @author Aaron Schulz + * Based on deleteOldRevisions.php by Rob Church + */ + +$options = array( 'delete', 'help' ); +require_once( 'commandLine.inc' ); +require_once( 'deleteArchivedFiles.inc' ); + +echo( "Delete Archived Images\n\n" ); + +if( @$options['help'] ) { + ShowUsage(); +} else { + DeleteArchivedFiles( @$options['delete'] ); +} + +function ShowUsage() { + echo( "Deletes all archived images.\n\n" ); + echo( "These images will no longer be restorable.\n\n" ); + echo( "Usage: php deleteArchivedRevisions.php [--delete|--help]\n\n" ); + echo( "delete : Performs the deletion\n" ); + echo( " help : Show this usage information\n" ); +} + diff --git a/maintenance/deleteArchivedRevisions.inc b/maintenance/deleteArchivedRevisions.inc new file mode 100644 index 00000000..f820ccb0 --- /dev/null +++ b/maintenance/deleteArchivedRevisions.inc @@ -0,0 +1,35 @@ +<?php + +/** + * Support functions for the deleteArchivedRevisions script + * + * @addtogroup Maintenance + * @author Aaron Schulz + */ + +require_once( 'purgeOldText.inc' ); + +function DeleteArchivedRevisions( $delete = false ) { + + # Data should come off the master, wrapped in a transaction + $dbw = wfGetDB( DB_MASTER ); + $dbw->begin(); + + $tbl_arch = $dbw->tableName( 'archive' ); + # Delete as appropriate + echo( "Deleting archived revisions..." ); + $dbw->query( "TRUNCATE TABLE $tbl_arch" ); + echo( "done.\n" ); + + $delete = $dbw->affectedRows() != 0; + + # This bit's done + # Purge redundant text records + $dbw->commit(); + if( $delete ) { + PurgeRedundantText( true ); + } + +} + +?>
\ No newline at end of file diff --git a/maintenance/deleteArchivedRevisions.php b/maintenance/deleteArchivedRevisions.php new file mode 100644 index 00000000..53aec4c3 --- /dev/null +++ b/maintenance/deleteArchivedRevisions.php @@ -0,0 +1,30 @@ +<?php + +/** + * Delete arcived (deleted from public) revisions from the database + * + * @addtogroup Maintenance + * @author Aaron Schulz + * Shamelessly stolen from deleteOldRevisions.php by Rob Church :) + */ + +$options = array( 'delete', 'help' ); +require_once( 'commandLine.inc' ); +require_once( 'deleteArchivedRevisions.inc' ); + +echo( "Delete Archived Revisions\n\n" ); + +if( @$options['help'] ) { + ShowUsage(); +} else { + DeleteArchivedRevisions( @$options['delete'] ); +} + +function ShowUsage() { + echo( "Deletes all archived revisions.\n\n" ); + echo( "These revisions will no longer be restorable.\n\n" ); + echo( "Usage: php deleteArchivedRevisions.php [--delete|--help]\n\n" ); + echo( "delete : Performs the deletion\n" ); + echo( " help : Show this usage information\n" ); +} + diff --git a/maintenance/deleteBatch.php b/maintenance/deleteBatch.php index 3021b118..6821ee29 100644 --- a/maintenance/deleteBatch.php +++ b/maintenance/deleteBatch.php @@ -85,4 +85,4 @@ for ( $linenum = 1; !feof( $file ); $linenum++ ) { } -?> + diff --git a/maintenance/deleteDefaultMessages.php b/maintenance/deleteDefaultMessages.php index a649da4c..32e03494 100644 --- a/maintenance/deleteDefaultMessages.php +++ b/maintenance/deleteDefaultMessages.php @@ -1,7 +1,7 @@ <?php /** - * Deletes all pages in the MediaWiki namespace which were last edited by + * Deletes all pages in the MediaWiki namespace which were last edited by * "MediaWiki default". */ @@ -17,7 +17,7 @@ function deleteDefaultMessages() { global $wgUser; $wgUser = User::newFromName( $user ); $wgUser->addGroup( 'bot' ); - + $dbr = wfGetDB( DB_SLAVE ); $res = $dbr->select( array( 'page', 'revision' ), array( 'page_namespace', 'page_title' ), @@ -42,4 +42,4 @@ function deleteDefaultMessages() { $dbw->commit(); } } -?> + diff --git a/maintenance/deleteImageMemcached.php b/maintenance/deleteImageMemcached.php index 267c2a6b..7ec9953c 100644 --- a/maintenance/deleteImageMemcached.php +++ b/maintenance/deleteImageMemcached.php @@ -57,4 +57,4 @@ $report = (int)$options['report']; $dic = new DeleteImageCache( $until, $sleep, $report ); $dic->main(); -?> + diff --git a/maintenance/deleteOldRevisions.php b/maintenance/deleteOldRevisions.php index 404f1353..8d676ab1 100644 --- a/maintenance/deleteOldRevisions.php +++ b/maintenance/deleteOldRevisions.php @@ -26,4 +26,3 @@ function ShowUsage() { echo( " help : Show this usage information\n" ); } -?>
\ No newline at end of file diff --git a/maintenance/deleteOrphanedRevisions.inc.php b/maintenance/deleteOrphanedRevisions.inc.php index c935a1c2..707eaf98 100644 --- a/maintenance/deleteOrphanedRevisions.inc.php +++ b/maintenance/deleteOrphanedRevisions.inc.php @@ -29,4 +29,3 @@ function showUsage() { echo( " --report : Prints out a count of affected revisions but doesn't delete them\n\n" ); } -?>
\ No newline at end of file diff --git a/maintenance/deleteOrphanedRevisions.php b/maintenance/deleteOrphanedRevisions.php index 302099e6..0842018e 100644 --- a/maintenance/deleteOrphanedRevisions.php +++ b/maintenance/deleteOrphanedRevisions.php @@ -51,4 +51,3 @@ $dbw->immediateCommit(); require_once( 'purgeOldText.inc' ); PurgeRedundantText( true ); -?>
\ No newline at end of file diff --git a/maintenance/deleteRevision.php b/maintenance/deleteRevision.php index af972600..0876efc9 100644 --- a/maintenance/deleteRevision.php +++ b/maintenance/deleteRevision.php @@ -37,4 +37,4 @@ foreach ( $args as $revID ) { } print "Deleted $affected revisions\n"; -?> + diff --git a/maintenance/dumpBackup.php b/maintenance/dumpBackup.php index 8e0941e2..9ec5674d 100644 --- a/maintenance/dumpBackup.php +++ b/maintenance/dumpBackup.php @@ -26,8 +26,7 @@ $originalDir = getcwd(); $optionsWithArgs = array( 'pagelist', 'start', 'end' ); require_once( 'commandLine.inc' ); -require_once( 'SpecialExport.php' ); -require_once( 'maintenance/backup.inc' ); +require_once( 'backup.inc' ); $dumper = new BackupDumper( $argv ); @@ -95,4 +94,4 @@ END ); } -?> + diff --git a/maintenance/dumpHTML.inc b/maintenance/dumpHTML.inc index ca2a7df6..18f5a9d7 100644 --- a/maintenance/dumpHTML.inc +++ b/maintenance/dumpHTML.inc @@ -9,6 +9,10 @@ require_once( 'includes/ImagePage.php' ); require_once( 'includes/CategoryPage.php' ); require_once( 'includes/RawPage.php' ); +# Explicitly disable article view counter (bug 6823) +global $wgDisableCounters; +$wgDisableCounters = true; + class DumpHTML { # Destination directory var $dest; diff --git a/maintenance/dumpHTML.php b/maintenance/dumpHTML.php index b9b052ed..26e914ff 100644 --- a/maintenance/dumpHTML.php +++ b/maintenance/dumpHTML.php @@ -4,33 +4,38 @@ * @addtogroup Maintenance */ -/** - * Usage: - * php dumpHTML.php [options...] - * - * -d <dest> destination directory - * -s <start> start ID - * -e <end> end ID - * -k <skin> skin to use (defaults to htmldump) - * --no-overwrite skip existing HTML files - * --checkpoint <file> use a checkpoint file to allow restarting of interrupted dumps - * --slice <n/m> split the job into m segments and do the n'th one - * --images only do image description pages - * --shared-desc only do shared (commons) image description pages - * --no-shared-desc don't do shared image description pages - * --categories only do category pages - * --redirects only do redirects - * --special only do miscellaneous stuff - * --force-copy copy commons instead of symlink, needed for Wikimedia - * --interlang allow interlanguage links - * --image-snapshot copy all images used to the destination directory - * --compress generate compressed version of the html pages - * --udp-profile <N> profile 1/N rendering operations using ProfilerSimpleUDP - */ - +function ShowUsage() { +echo <<<END +Usage: +php dumpHTML.php --help +php dumpHTML.php [options...] + + --help show this message + + -d <dest> destination directory + -s <start> start ID + -e <end> end ID + -k <skin> skin to use (defaults to htmldump) + --no-overwrite skip existing HTML files + --checkpoint <file> use a checkpoint file to allow restarting of interrupted dumps + --slice <n/m> split the job into m segments and do the n'th one + --images only do image description pages + --shared-desc only do shared (commons) image description pages + --no-shared-desc don't do shared image description pages + --categories only do category pages + --redirects only do redirects + --special only do miscellaneous stuff + --force-copy copy commons instead of symlink, needed for Wikimedia + --interlang allow interlanguage links + --image-snapshot copy all images used to the destination directory + --compress generate compressed version of the html pages + --udp-profile <N> profile 1/N rendering operations using ProfilerSimpleUDP + +END; +} $optionsWithArgs = array( 's', 'd', 'e', 'k', 'checkpoint', 'slice', 'udp-profile' ); - +$options = array( 'help' ); $profiling = false; if ( $profiling ) { @@ -52,6 +57,11 @@ require_once( "dumpHTML.inc" ); error_reporting( E_ALL & (~E_NOTICE) ); +if( isset( $options['help'] ) ) { + ShowUsage(); + exit(); +} + if ( !empty( $options['s'] ) ) { $start = $options['s']; } else { @@ -147,4 +157,4 @@ if ( $profiling ) { echo $wgProfiler->getOutput(); } -?> + diff --git a/maintenance/dumpInterwiki.php b/maintenance/dumpInterwiki.php index ba3ac18b..02116a53 100644 --- a/maintenance/dumpInterwiki.php +++ b/maintenance/dumpInterwiki.php @@ -21,4 +21,4 @@ if ( isset( $options['o'] ) ) { } getRebuildInterwikiDump(); -?> + diff --git a/maintenance/dumpLinks.php b/maintenance/dumpLinks.php index 2caa873c..f61c398b 100644 --- a/maintenance/dumpLinks.php +++ b/maintenance/dumpLinks.php @@ -59,4 +59,4 @@ while( $row = $dbr->fetchObject( $result ) ) { if( isset( $lastPage ) ) print "\n"; -?> + diff --git a/maintenance/dumpSisterSites.php b/maintenance/dumpSisterSites.php index 45927b0d..0c2fff46 100644 --- a/maintenance/dumpSisterSites.php +++ b/maintenance/dumpSisterSites.php @@ -45,4 +45,4 @@ while( $row = $dbr->fetchObject( $result ) ) { $dbr->freeResult( $result ); -?> + diff --git a/maintenance/dumpTextPass.php b/maintenance/dumpTextPass.php index 494c5ad4..92ab4b4e 100644 --- a/maintenance/dumpTextPass.php +++ b/maintenance/dumpTextPass.php @@ -24,8 +24,7 @@ $originalDir = getcwd(); require_once( 'commandLine.inc' ); -require_once( 'SpecialExport.php' ); -require_once( 'maintenance/backup.inc' ); +require_once( 'backup.inc' ); /** * Stream wrapper around 7za filter program. @@ -240,17 +239,23 @@ class TextPassDumper extends BackupDumper { } while( true ) { try { - return $this->doGetText( $id ); + $text = $this->doGetText( $id ); + $ex = new MWException("Graceful storage failure"); } catch (DBQueryError $ex) { + $text = false; + } + if( $text === false ) { $this->failures++; if( $this->failures > $this->maxFailures ) { throw $ex; } else { $this->progress( "Database failure $this->failures " . - "of allowed $this->maxFailures! " . + "of allowed $this->maxFailures for revision $id! " . "Pausing $this->failureTimeout seconds..." ); sleep( $this->failureTimeout ); } + } else { + return $text; } } } @@ -265,6 +270,9 @@ class TextPassDumper extends BackupDumper { array( 'old_id' => $id ), 'TextPassDumper::getText' ); $text = Revision::getRevisionText( $row ); + if( $text === false ) { + return false; + } $stripped = str_replace( "\r", "", $text ); $normalized = UtfNormal::cleanUp( $stripped ); return $normalized; @@ -367,4 +375,4 @@ END ); } -?> + diff --git a/maintenance/dumpUploads.php b/maintenance/dumpUploads.php index 8ba4e87b..74a28380 100644 --- a/maintenance/dumpUploads.php +++ b/maintenance/dumpUploads.php @@ -113,4 +113,3 @@ END; $dumper = new UploadDumper( $options ); $dumper->run(); -?>
\ No newline at end of file diff --git a/maintenance/edit.php b/maintenance/edit.php index 33e0607b..75b6c333 100644 --- a/maintenance/edit.php +++ b/maintenance/edit.php @@ -65,4 +65,4 @@ if ( $success ) { print "failed\n"; exit( 1 ); } -?> + diff --git a/maintenance/eval.php b/maintenance/eval.php index 421db682..519411df 100644 --- a/maintenance/eval.php +++ b/maintenance/eval.php @@ -59,4 +59,4 @@ while ( ( $line = readconsole( '> ' ) ) !== false ) { print "\n"; -?> + diff --git a/maintenance/findhooks.php b/maintenance/findhooks.php index 0308ad13..284e7906 100644 --- a/maintenance/findhooks.php +++ b/maintenance/findhooks.php @@ -91,4 +91,4 @@ $deprecated = array_diff($documented, $potential); printArray('undocumented', $todo ); printArray('not found', $deprecated ); -?> + diff --git a/maintenance/fixSlaveDesync.php b/maintenance/fixSlaveDesync.php index aec77b1e..daa5bbb4 100644 --- a/maintenance/fixSlaveDesync.php +++ b/maintenance/fixSlaveDesync.php @@ -189,4 +189,4 @@ function desyncFixPage( $pageID ) { $dbw->commit(); } -?> + diff --git a/maintenance/fixTimestamps.php b/maintenance/fixTimestamps.php index abd861d4..39cdaae1 100644 --- a/maintenance/fixTimestamps.php +++ b/maintenance/fixTimestamps.php @@ -101,4 +101,4 @@ $sql = "UPDATE $revisionTable " . $dbw->query( $sql, $fname ); echo "Done\n"; -?> + diff --git a/maintenance/fixUserRegistration.php b/maintenance/fixUserRegistration.php index 471ef055..b342a86d 100644 --- a/maintenance/fixUserRegistration.php +++ b/maintenance/fixUserRegistration.php @@ -28,4 +28,4 @@ while ( $row = $dbr->fetchObject( $res ) ) { } print "\n"; -?> + diff --git a/maintenance/fuzz-tester.php b/maintenance/fuzz-tester.php index 4e90d52b..af12d6a1 100644 --- a/maintenance/fuzz-tester.php +++ b/maintenance/fuzz-tester.php @@ -545,6 +545,8 @@ class wikiFuzz { "Image:", "[[:Image", 'px', + 'upright=', + 'border', // misc stuff to throw at the Parser. '%08X', @@ -621,7 +623,7 @@ class wikiFuzz { "{{ns:0}}", "{{fullurle:", "}}", - "{{subst:", + "{{subst::", "}}", "{{UCFIRST:", "}}", @@ -2165,23 +2167,23 @@ class api extends pageTest { */ class GeSHi_Test extends pageTest { - private function getGeSHiContent() { - return "<source lang=\"" . $this->getLang() . "\" " - . (wikiFuzz::randnum(2) == 0 ? "line " : "") - . (wikiFuzz::randnum(2) == 0 ? "strict " : "") - . "start=" . wikiFuzz::chooseInput( array(wikiFuzz::randnum(-6000,6000), wikifuzz::makeFuzz(2)) ) - . ">" - . wikiFuzz::makeFuzz(2) - . "</source>"; - } + private function getGeSHiContent() { + return "<source lang=\"" . $this->getLang() . "\" " + . (wikiFuzz::randnum(2) == 0 ? "line " : "") + . (wikiFuzz::randnum(2) == 0 ? "strict " : "") + . "start=" . wikiFuzz::chooseInput( array(wikiFuzz::randnum(-6000,6000), wikifuzz::makeFuzz(2)) ) + . ">" + . wikiFuzz::makeFuzz(2) + . "</source>"; + } - private function getLang() { - return wikiFuzz::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp", "cfdg", "cfm", "cpp", "cpp-qt", - "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl", "ini", "inno", "io", "java", "java5", - "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas", "oracle8", "pascal", "perl", "php", - "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty", "sql", "tcl", "text", "thinbasic", - "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikifuzz::makeFuzz(1) ) ); - } + private function getLang() { + return wikiFuzz::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp", + "cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl", + "ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas", + "oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty", + "sql", "tcl", "text", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikifuzz::makeFuzz(1) ) ); + } function __construct() { $this->pagePath = "index.php?title=WIKIFUZZ"; @@ -2744,4 +2746,4 @@ for ($count=0; true; $count++) { } } -?> + diff --git a/maintenance/generateSitemap.php b/maintenance/generateSitemap.php index 7fff0069..657437bc 100644 --- a/maintenance/generateSitemap.php +++ b/maintenance/generateSitemap.php @@ -10,8 +10,8 @@ define( 'GS_TALK', -1 ); * @copyright Copyright © 2005, Jens Frank <jeluf@gmx.de> * @copyright Copyright © 2005, Brion Vibber <brion@pobox.com> * - * @link http://www.google.com/webmasters/sitemaps/docs/en/about.html - * @link http://www.google.com/schemas/sitemap/0.84/sitemap.xsd + * @see http://www.google.com/webmasters/sitemaps/docs/en/about.html + * @see http://www.google.com/schemas/sitemap/0.84/sitemap.xsd * * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later */ @@ -471,4 +471,4 @@ if ( isset( $options['server'] ) ) { $gs = new GenerateSitemap( @$options['fspath'], @$options['compress'] !== 'no' ); $gs->main(); -?> + diff --git a/maintenance/getLagTimes.php b/maintenance/getLagTimes.php index 5c55d52c..d3934592 100644 --- a/maintenance/getLagTimes.php +++ b/maintenance/getLagTimes.php @@ -21,4 +21,3 @@ if( empty( $wgDBservers ) ) { } } -?>
\ No newline at end of file diff --git a/maintenance/getSlaveServer.php b/maintenance/getSlaveServer.php index 5e1b0689..9aca1043 100644 --- a/maintenance/getSlaveServer.php +++ b/maintenance/getSlaveServer.php @@ -12,4 +12,4 @@ if( isset( $options['group'] ) ) { print "$host\n"; -?> + diff --git a/maintenance/importDump.php b/maintenance/importDump.php index c7d36042..211d0a9e 100644 --- a/maintenance/importDump.php +++ b/maintenance/importDump.php @@ -24,7 +24,6 @@ $optionsWithArgs = array( 'report' ); require_once( 'commandLine.inc' ); -require_once( 'SpecialImport.php' ); class BackupReader { var $reportingInterval = 100; @@ -139,4 +138,4 @@ if( WikiError::isError( $result ) ) { echo "the recentchanges page.\n"; } -?> + diff --git a/maintenance/importImages.inc.php b/maintenance/importImages.inc.php index c8fbc541..9a68bac0 100644 --- a/maintenance/importImages.inc.php +++ b/maintenance/importImages.inc.php @@ -45,22 +45,4 @@ function splitFilename( $filename ) { unset( $parts[ count( $parts ) - 1 ] ); $fname = implode( '.', $parts ); return array( $fname, $ext ); -} - -/** - * Given an image hash, check that the structure exists to save the image file - * and create it if it doesn't - * - * @param $hash Part of an image hash, e.g. /f/fd/ - */ -function makeHashPath( $hash ) { - global $wgUploadDirectory; - $parts = explode( '/', substr( $hash, 1, strlen( $hash ) - 2 ) ); - if( !is_dir( $wgUploadDirectory . '/' . $parts[0] ) ) - mkdir( $wgUploadDirectory . '/' . $parts[0] ); - if( !is_dir( $wgUploadDirectory . '/' . $hash ) ) - mkdir( $wgUploadDirectory . '/' . $hash ); -} - - -?>
\ No newline at end of file +}
\ No newline at end of file diff --git a/maintenance/importImages.php b/maintenance/importImages.php index 8302982c..660d831c 100644 --- a/maintenance/importImages.php +++ b/maintenance/importImages.php @@ -8,21 +8,26 @@ * @author Rob Church <robchur@gmail.com> */ +$optionsWithArguments = array( 'extensions', 'overwrite' ); require_once( 'commandLine.inc' ); require_once( 'importImages.inc.php' ); +$added = $skipped = $overwritten = 0; + echo( "Import Images\n\n" ); -# Need a directory and at least one extension -if( count( $args ) > 1 ) { +# Need a path +if( count( $args ) > 0 ) { - $dir = array_shift( $args ); + $dir = $args[0]; - # Check the allowed extensions - while( $ext = array_shift( $args ) ) - $exts[] = ltrim( $ext, '.' ); - - # Search the directory given and pull out suitable candidates - $files = findFiles( $dir, $exts ); + # Prepare the list of allowed extensions + global $wgFileExtensions; + $extensions = isset( $options['extensions'] ) + ? explode( ',', strtolower( $options['extensions'] ) ) + : $wgFileExtensions; + + # Search the path provided for candidates for import + $files = findFiles( $dir, $extensions ); # Initialise the user for this operation $user = isset( $options['user'] ) @@ -31,68 +36,72 @@ if( count( $args ) > 1 ) { if( !$user instanceof User ) $user = User::newFromName( 'Maintenance script' ); $wgUser = $user; - + # Get the upload comment $comment = isset( $options['comment'] ) ? $options['comment'] : 'Importing image file'; - + # Get the license specifier $license = isset( $options['license'] ) ? $options['license'] : ''; - + # Batch "upload" operation - foreach( $files as $file ) { + if( ( $count = count( $files ) ) > 0 ) { + + foreach( $files as $file ) { + $base = wfBaseName( $file ); + + # Validate a title + $title = Title::makeTitleSafe( NS_IMAGE, $base ); + if( !is_object( $title ) ) { + echo( "{$base} could not be imported; a valid title cannot be produced\n" ); + continue; + } - $base = wfBaseName( $file ); - - # Validate a title - $title = Title::makeTitleSafe( NS_IMAGE, $base ); - if( is_object( $title ) ) { - # Check existence - $image = new Image( $title ); - if( !$image->exists() ) { - - global $wgUploadDirectory; - - # copy() doesn't create paths so if the hash path doesn't exist, we - # have to create it - makeHashPath( wfGetHashPath( $image->name ) ); - - # Stash the file - echo( "Saving {$base}..." ); - - if( copy( $file, $image->getFullPath() ) ) { - - echo( "importing..." ); - - # Grab the metadata - $image->loadFromFile(); - - # Record the upload - if( $image->recordUpload( '', $comment, $license ) ) { - - # We're done! - echo( "done.\n" ); - - } else { - echo( "failed.\n" ); - } - + $image = wfLocalFile( $title ); + if( $image->exists() ) { + if( isset( $options['overwrite'] ) ) { + echo( "{$base} exists, overwriting..." ); + $svar = 'overwritten'; } else { - echo( "failed.\n" ); + echo( "{$base} exists, skipping\n" ); + $skipped++; + continue; } - } else { - echo( "{$base} could not be imported; a file with this name exists in the wiki\n" ); + echo( "Importing {$base}..." ); + $svar = 'added'; + } + + # Import the file + $archive = $image->publish( $file ); + if( WikiError::isError( $archive ) || !$archive->isGood() ) { + echo( "failed.\n" ); + continue; + } + + $$svar++; + if ( $image->recordUpload( $archive->value, $comment, $license ) ) { + # We're done! + echo( "done.\n" ); + } else { + echo( "failed.\n" ); } + + } - } else { - echo( "{$base} could not be imported; a valid title cannot be produced\n" ); + # Print out some statistics + echo( "\n" ); + foreach( array( 'count' => 'Found', 'added' => 'Added', + 'skipped' => 'Skipped', 'overwritten' => 'Overwritten' ) as $var => $desc ) { + if( $$var > 0 ) + echo( "{$desc}: {$$var}\n" ); } + } else { + echo( "No suitable files could be found for import.\n" ); } - } else { showUsage(); @@ -101,21 +110,23 @@ if( count( $args ) > 1 ) { exit(); function showUsage( $reason = false ) { - if( $reason ) + if( $reason ) { echo( $reason . "\n" ); + } + echo <<<END -USAGE: php importImages.php [options] <dir> <ext1> ... +Imports images and other media files into the wiki +USAGE: php importImages.php [options] <dir> <dir> : Path to the directory containing images to be imported -<ext1+> File extensions to import Options: ---user=<username> Set username of uploader, default 'Image import script' ---comment=<text> Set upload summary comment, default 'Importing image file' ---license=<code> Use an optional license template +--extensions=<exts> Comma-separated list of allowable extensions, defaults to \$wgFileExtensions +--overwrite Overwrite existing images if a conflicting-named image is found +--user=<username> Set username of uploader, default 'Maintenance script' +--comment=<text> Set upload summary comment, default 'Importing image file' +--license=<code> Use an optional license template END; exit(); -} - -?> +}
\ No newline at end of file diff --git a/maintenance/importLogs.php b/maintenance/importLogs.php index 54cee1dd..199a7f0c 100644 --- a/maintenance/importLogs.php +++ b/maintenance/importLogs.php @@ -23,4 +23,4 @@ foreach( LogPage::validTypes() as $type ) { $importer->importText( $text ); } -?> + diff --git a/maintenance/importTextFile.php b/maintenance/importTextFile.php index 60ee228e..676acbdb 100644 --- a/maintenance/importTextFile.php +++ b/maintenance/importTextFile.php @@ -83,4 +83,3 @@ function showHelp() { echo( "\n" ); } -?>
\ No newline at end of file diff --git a/maintenance/importUseModWiki.php b/maintenance/importUseModWiki.php index ae5dd23b..4febc497 100644 --- a/maintenance/importUseModWiki.php +++ b/maintenance/importUseModWiki.php @@ -45,7 +45,7 @@ $wgFieldSeparator = "\xb3"; # Some wikis may use different char $FS3 = $FS."3" ; # Unicode sanitization tools -require_once( '../includes/normal/UtfNormal.php' ); +require_once( dirname( dirname( __FILE__ ) ) . '/includes/normal/UtfNormal.php' ); $usercache = array(); @@ -362,4 +362,4 @@ function nowikiPlaceholder( $matches ) { return placeholder(); } -?> + diff --git a/maintenance/initEditCount.php b/maintenance/initEditCount.php index 9d165cfb..5a4367d0 100644 --- a/maintenance/initEditCount.php +++ b/maintenance/initEditCount.php @@ -82,4 +82,4 @@ if( $backgroundMode ) { echo "Done!\n"; -?> + diff --git a/maintenance/initStats.php b/maintenance/initStats.php index 850d816c..05377481 100644 --- a/maintenance/initStats.php +++ b/maintenance/initStats.php @@ -28,4 +28,3 @@ function showHelp() { echo( "--noviews : Don't update the page view counter\n\n" ); } -?>
\ No newline at end of file diff --git a/maintenance/installExtension.php b/maintenance/installExtension.php index 063002f5..549c4a68 100644 --- a/maintenance/installExtension.php +++ b/maintenance/installExtension.php @@ -652,4 +652,4 @@ if ( $ok ) $ok = $installer->patchLocalSettings( $mode ); if ( $ok ) $ok = $installer->printNotices(); if ( $ok ) $installer->note( "$name extension installed." ); -?> + diff --git a/maintenance/interwiki.sql b/maintenance/interwiki.sql index 0eae287a..cfa25d9e 100644 --- a/maintenance/interwiki.sql +++ b/maintenance/interwiki.sql @@ -3,35 +3,26 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES ('abbenormal','http://www.ourpla.net/cgi-bin/pikie.cgi?$1',0), -('acadwiki','http://xarch.tu-graz.ac.at/autocad/wiki/$1',0), ('acronym','http://www.acronymfinder.com/af-query.asp?String=exact&Acronym=$1',0), ('advogato','http://www.advogato.org/$1',0), ('aiwiki','http://www.ifi.unizh.ch/ailab/aiwiki/aiw.cgi?$1',0), -('alife','http://news.alife.org/wiki/index.php?$1',0), -('annotation','http://bayle.stanford.edu/crit/nph-med.cgi/$1',0), ('annotationwiki','http://www.seedwiki.com/page.cfm?wikiid=368&doc=$1',0), ('arxiv','http://www.arxiv.org/abs/$1',0), -('aspienetwiki','http://aspie.mela.de/Wiki/index.php?title=$1',0), ('bemi','http://bemi.free.fr/vikio/index.php?$1',0), -('benefitswiki','http://www.benefitslink.com/cgi-bin/wiki.cgi?$1',0), -('brasilwiki','http://rio.ifi.unizh.ch/brasilienwiki/index.php/$1',0), -('bridgeswiki','http://c2.com/w2/bridges/$1',0), ('c2find','http://c2.com/cgi/wiki?FindPage&value=$1',0), ('cache','http://www.google.com/search?q=cache:$1',0), -('ciscavate','http://ciscavate.org/index.php/$1',0), ('cliki','http://ww.telent.net/cliki/$1',0), ('cmwiki','http://www.ourpla.net/cgi-bin/wiki.pl?$1',0), -('codersbase','http://www.codersbase.com/$1',0), +('codersbase','http://www.codersbase.com/index.php/$1',0), ('commons','http://commons.wikimedia.org/wiki/$1',0), ('consciousness','http://teadvus.inspiral.org/',0), ('corpknowpedia','http://corpknowpedia.org/wiki/index.php/$1',0), ('creationmatters','http://www.ourpla.net/cgi-bin/wiki.pl?$1',0), ('dejanews','http://www.deja.com/=dnc/getdoc.xp?AN=$1',0), -('demokraatia','http://wiki.demokraatia.ee/',0), ('dictionary','http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query=$1',0), ('disinfopedia','http://www.disinfopedia.org/wiki.phtml?title=$1',0), ('diveintoosx','http://diveintoosx.org/$1',0), -('docbook','http://docbook.org/wiki/moin.cgi/$1',0), +('docbook','http://wiki.docbook.org/topic/$1',0), ('dolphinwiki','http://www.object-arts.com/wiki/html/Dolphin/$1',0), ('drumcorpswiki','http://www.drumcorpswiki.com/index.php/$1',0), ('dwjwiki','http://www.suberic.net/cgi-bin/dwj/wiki.cgi?$1',0), @@ -166,7 +157,7 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES ('wikinfo','http://www.wikinfo.org/wiki.php?title=$1',0), ('wikimedia','http://wikimediafoundation.org/wiki/$1',0), ('wikiquote','http://en.wikiquote.org/wiki/$1',1), -('wikinews','http://en.wikinews.org/wiki/$1',0), +('wikinews','http://en.wikinews.org/wiki/$1',1), ('wikisource','http://sources.wikipedia.org/wiki/$1',1), ('wikispecies','http://species.wikipedia.org/wiki/$1',1), ('wikitravel','http://wikitravel.org/en/$1',0), diff --git a/maintenance/language/alltrans.php b/maintenance/language/alltrans.php index 69b9a4ea..4adc2a66 100644 --- a/maintenance/language/alltrans.php +++ b/maintenance/language/alltrans.php @@ -12,4 +12,4 @@ foreach( $wgEnglishMessages as $key ) { echo "$key\n"; } -?> + diff --git a/maintenance/language/checkExtensions.php b/maintenance/language/checkExtensions.php new file mode 100644 index 00000000..1cfb0de8 --- /dev/null +++ b/maintenance/language/checkExtensions.php @@ -0,0 +1,269 @@ +<?php +/** + * Copyright (C) 2007 Ashar Voultoiz <hashar@altern.org> + * + * Based on dumpBackup: + * Copyright (C) 2005 Brion Vibber <brion@pobox.com> + * + * http://www.mediawiki.org + * + * 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 + * + * @addtogroup Maintenance + */ + +# +# Lacking documentation. Examples: +# php checkExtensions.php /opt/mw/extensions/CentralAuth/CentralAuth.i18n.php wgCentralAuthMessages +# php checkExtensions.php --extdir /opt/mw/extensions/ +# +# BUGS: cant guess registered extensions :) +# TODO: let users set parameters to configure checklanguage.inc + +// Filename for the extension i18n files database: +define( 'EXT_I18N_DB', 'i18n.db' ); + +$optionsWithArgs = array( 'extdir', 'lang' ); + +require_once( dirname(__FILE__).'/../commandLine.inc' ); +require_once( 'languages.inc' ); +require_once( 'checkLanguage.inc' ); + + +class extensionLanguages extends languages { + private $mExt18nFilename, $mExtArrayName ; + private $mExtArray; + + function __construct( $ext18nFilename, $extArrayName ) { + $this->mExt18nFilename = $ext18nFilename; + $this->mExtArrayName = $extArrayName; + + $this->mIgnoredMessages = array(); + $this->mOptionalMessages = array(); + + if ( file_exists( $this->mExt18nFilename ) ) { + require_once( $this->mExt18nFilename ); + + $foundarray = false; + if( isset( ${$this->mExtArrayName} ) ) { + // File provided in the db file + $foundarray = ${$this->mExtArrayName}; + } else { + + /* For extensions included elsewhere. For some reason other extensions + * break with the global statement, so recheck here. + */ + global ${$this->mExtArrayName}; + if( is_array( ${$this->mExtArrayName} ) ) { + $foundarray = ${$this->mExtArrayName}; + } + + /* we might have been given a function name, test it too */ + if( function_exists( $this->mExtArrayName ) ) { + // Load data + $funcName = $this->mExtArrayName ; + $foundarray = $funcName(); + } + + if(!$foundarray) { + // Provided array could not be found we try to guess it. + + # Using the extension path ($m[1]) and filename ($m[2]): + $m = array(); + preg_match( '%.*/(.*)/(.*).i18n\.php%', $this->mExt18nFilename, $m); + $arPathCandidate = 'wg' . $m[1].'Messages'; + $arFileCandidate = 'wg' . $m[2].'Messages'; + $funcCandidate = "ef{$m[2]}Messages"; + + // Try them: + if( isset($$arPathCandidate) && is_array( $$arPathCandidate ) ) { + print "warning> messages from guessed path array \$$arPathCandidate.\n"; + $foundarray = $$arPathCandidate; + } elseif( isset($$arFileCandidate) && is_array( $$arFileCandidate ) ) { + print "warning> messages from guessed file array \$$arFileCandidate.\n"; + $foundarray = $$arFileCandidate; + } elseif( function_exists( $funcCandidate ) ) { + print "warning> messages build from guessed function {$funcCandidate}().\n"; + $foundarray = $funcCandidate(); + } + } + + # We are unlucky, return empty stuff + if(!$foundarray) { + print "ERROR> failed to guess an array to use.\n"; + $this->mExtArray = null; + $this->mLanguages = null; + return; + } + } + + $this->mExtArray = $foundarray ; + $this->mLanguages = array_keys( $this->mExtArray ); + } else { + wfDie( "File $this->mExt18nFilename not found\n" ); + } + } + + protected function loadRawMessages( $code ) { + if ( isset( $this->mRawMessages[$code] ) ) { + return; + } + if( isset( $this->mExtArray[$code] ) ) { + $this->mRawMessages[$code] = $this->mExtArray[$code] ; + } else { + $this->mRawMessages[$code] = array(); + } + } + + public function getLanguages() { + return $this->mLanguages; + } +} + +/** + * @param $filename Filename containing the extension i18n + * @param $arrayname The name of the array in the filename + * @param $filter Optional, restrict check to a given language code (default; null) + */ +function checkExtensionLanguage( $filename, $arrayname, $filter = null ) { + $extLanguages = new extensionLanguages($filename, $arrayname); + + $langs = $extLanguages->getLanguages(); + if( !$langs ) { + print "ERROR> \$$arrayname array does not exist.\n"; + return false; + } + + $nErrors = 0; + if( $filter ) { + $nErrors += checkLanguage( $extLanguages, $filter ); + } else { + print "Will check ". count($langs) . " languages : " . implode(' ', $langs) .".\n"; + foreach( $langs as $lang ) { + if( $lang == 'en' ) { + #print "Skipped english language\n"; + continue; + } + + $nErrors += checkLanguage( $extLanguages, $lang ); + } + } + + return $nErrors; +} + +/** + * Read the db file, parse it, start the check. + */ +function checkExtensionRepository( $extdir, $db ) { + $fh = fopen( $extdir. '/' . $db, 'r' ); + + $line_number = 0; + while( $line = fgets( $fh ) ) { + $line_number++; + + // Ignore comments + if( preg_match( '/^#/', $line ) ) { + continue; + } + + // Load data from i18n database + $data = split( ' ', chop($line) ); + $i18n_file = @$data[0]; + $arrayname = @$data[1]; + + print "------------------------------------------------------\n"; + print "Checking $i18n_file (\$$arrayname).\n"; + + // Check data + if( !file_exists( $extdir . '/' . $i18n_file ) ) { + print "ERROR> $i18n_file not found ($db:$line_number).\n"; + continue; + } +# if( $arrayname == '' ) { +# print "warning> no array name for $i18n_file ($db:$line_number).\n"; +# } + + $i18n_file = $extdir . '/' . $i18n_file ; + + global $myLang; + $nErrors = checkExtensionLanguage( $i18n_file, $arrayname, $myLang ); + if($nErrors == 1 ) { + print "\nFound $nErrors error for this extension.\n"; + } elseif($nErrors) { + print "\nFound $nErrors errors for this extension.\n"; + } else { + print "Looks OK.\n"; + } + + print "\n"; + } +} + + +function usage() { +// Usage +print <<<END +Usage: + php checkExtensions.php <filename> <arrayname> + php checkExtensions.php --extdir <extension repository> + +Common option: + --lang <language code> : only check the given language. + + +END; +die; +} + +// Play with options and arguments +$myLang = isset($options['lang']) ? $options['lang'] : null; + +if( isset( $options['extdir'] ) ) { + $extdb = $options['extdir'] . '/' . EXT_I18N_DB ; + + if( file_exists( $extdb ) ) { + checkExtensionRepository( $options['extdir'], EXT_I18N_DB ); + } else { + print "$extdb does not exist\n"; + } + +} else { + // Check arguments + if ( isset( $argv[0] ) ) { + + if (file_exists( $argv[0] ) ) { + $filename = $argv[0]; + } else { + print "Unable to open file '{$argv[0]}'\n"; + usage(); + } + + if ( isset( $argv[1] ) ) { + $arrayname = $argv[1]; + } else { + print "You must give an array name to be checked\n"; + usage(); + } + + global $myLang; + checkExtensionLanguage( $filename, $arrayname, $myLang ); + } else { + usage(); + } +} + + diff --git a/maintenance/language/checkLanguage.inc b/maintenance/language/checkLanguage.inc index e859e39c..468db550 100644 --- a/maintenance/language/checkLanguage.inc +++ b/maintenance/language/checkLanguage.inc @@ -2,91 +2,108 @@ /** * Check a language. * - * @todo Stop with globals. - * @param $code The language code. + * @param $languages The languages object. + * @param $code The language code (default content language of the wiki running the script on). + * @param: $links Show wiki links to messages (default false)? + * @param: $wikiLanguage Language of the wiki to show the output in, if showing links (default en). + * @param: $checks Checks to do (default all except for duplicates and plural). * @return Number of errors found. */ -function checkLanguage( $wgLanguages, $code ) { - global $wgRequiredMessagesNumber, $wgDisplayLevel, $wgLinks, $wgWikiLanguage, $wgChecks; - +function checkLanguage( $languages, $code = null, $displayLevel = 2, $links = false, $wikiLanguage = 'en', $checks = null ) { # Get messages - $messages = $wgLanguages->getMessages( $code ); + $messages = $languages->getMessages( $code ); $messagesNumber = count( $messages['translated'] ); - # Skip the checks if specified - if ( $wgDisplayLevel == 0 ) { + # Skip the checks if told so + if ( $displayLevel == 0 ) { return; } - // Initialize counts - $untranslatedMessagesNumber = $duplicateMessagesNumber = $obsoleteMessagesNumber - = $messagesWithoutVariablesNumber = $messagesWithoutPluralNumber = $emptyMessagesNumber - = $messagesWithWhitespaceNumber = $nonXHTMLMessagesNumber = $messagesWithWrongCharsNumber - = 0; + # Initialize counts + $problems = 0; + + # Set default language code and checks + if ( !$code ) { + global $wgContLang; + $code = $wgContLang->getCode(); + } + if ( !$checks ) { + $checks = array( 'untranslated', 'obsolete', 'variables', 'empty', 'whitespace', 'xhtml', 'chars' ); + } # Untranslated messages - if ( in_array( 'untranslated', $wgChecks ) ) { - $untranslatedMessages = $wgLanguages->getUntranslatedMessages( $code ); + if ( in_array( 'untranslated', $checks ) ) { + $generalMessages = $languages->getGeneralMessages(); + $requiredMessagesNumber = count( $generalMessages['required'] ); + $untranslatedMessages = $languages->getUntranslatedMessages( $code ); $untranslatedMessagesNumber = count( $untranslatedMessages ); - $wgLanguages->outputMessagesList( $untranslatedMessages, $code, "\n$untranslatedMessagesNumber messages of $wgRequiredMessagesNumber are not translated to $code, but exist in en:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $untranslatedMessages, $code, "\n$untranslatedMessagesNumber messages of $requiredMessagesNumber are not translated to $code, but exist in en:", $displayLevel, $links, $wikiLanguage ); + $problems += $untranslatedMessagesNumber; } # Duplicate messages - if ( in_array( 'duplicate', $wgChecks ) ) { - $duplicateMessages = $wgLanguages->getDuplicateMessages( $code ); + if ( in_array( 'duplicate', $checks ) ) { + $duplicateMessages = $languages->getDuplicateMessages( $code ); $duplicateMessagesNumber = count( $duplicateMessages ); - $wgLanguages->outputMessagesList( $duplicateMessages, $code, "\n$duplicateMessagesNumber messages of $messagesNumber are translated the same in en and $code:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $duplicateMessages, $code, "\n$duplicateMessagesNumber messages of $messagesNumber are translated the same in en and $code:", $displayLevel, $links, $wikiLanguage ); + $problems += $duplicateMessagesNumber; } # Obsolete messages - if ( in_array( 'obsolete', $wgChecks ) ) { + if ( in_array( 'obsolete', $checks ) ) { $obsoleteMessages = $messages['obsolete']; $obsoleteMessagesNumber = count( $obsoleteMessages ); - $wgLanguages->outputMessagesList( $obsoleteMessages, $code, "\n$obsoleteMessagesNumber messages of $messagesNumber are not exist in en (or are in the ignored list), but still exist in $code:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $obsoleteMessages, $code, "\n$obsoleteMessagesNumber messages of $messagesNumber do not exist in en (or are in the ignored list), but still exist in $code:", $displayLevel, $links, $wikiLanguage ); + $problems += $obsoleteMessagesNumber; } # Messages without variables - if ( in_array( 'variables', $wgChecks ) ) { - $messagesWithoutVariables = $wgLanguages->getMessagesWithoutVariables( $code ); + if ( in_array( 'variables', $checks ) ) { + $messagesWithoutVariables = $languages->getMessagesWithoutVariables( $code ); $messagesWithoutVariablesNumber = count( $messagesWithoutVariables ); - $wgLanguages->outputMessagesList( $messagesWithoutVariables, $code, "\n$messagesWithoutVariablesNumber messages of $messagesNumber in $code don't use some variables while en uses them:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $messagesWithoutVariables, $code, "\n$messagesWithoutVariablesNumber messages of $messagesNumber in $code don't use some variables while en uses them:", $displayLevel, $links, $wikiLanguage ); + $problems += $messagesWithoutVariablesNumber; } # Messages without plural - if ( in_array( 'plural', $wgChecks ) ) { - $messagesWithoutPlural = $wgLanguages->getMessagesWithoutPlural( $code ); + if ( in_array( 'plural', $checks ) ) { + $messagesWithoutPlural = $languages->getMessagesWithoutPlural( $code ); $messagesWithoutPluralNumber = count( $messagesWithoutPlural ); - $wgLanguages->outputMessagesList( $messagesWithoutPlural, $code, "\n$messagesWithoutPluralNumber messages of $messagesNumber in $code don't use {{plural}} while en uses it:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $messagesWithoutPlural, $code, "\n$messagesWithoutPluralNumber messages of $messagesNumber in $code don't use {{plural}} while en uses it:", $displayLevel, $links, $wikiLanguage ); + $problems += $messagesWithoutPluralNumber; } # Empty messages - if ( in_array( 'empty', $wgChecks ) ) { - $emptyMessages = $wgLanguages->getEmptyMessages( $code ); + if ( in_array( 'empty', $checks ) ) { + $emptyMessages = $languages->getEmptyMessages( $code ); $emptyMessagesNumber = count( $emptyMessages ); - $wgLanguages->outputMessagesList( $emptyMessages, $code, "\n$emptyMessagesNumber messages of $messagesNumber in $code are empty or -:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $emptyMessages, $code, "\n$emptyMessagesNumber messages of $messagesNumber in $code are empty or -:", $displayLevel, $links, $wikiLanguage ); + $problems += $emptyMessagesNumber; } # Messages with whitespace - if ( in_array( 'whitespace', $wgChecks ) ) { - $messagesWithWhitespace = $wgLanguages->getMessagesWithWhitespace( $code ); + if ( in_array( 'whitespace', $checks ) ) { + $messagesWithWhitespace = $languages->getMessagesWithWhitespace( $code ); $messagesWithWhitespaceNumber = count( $messagesWithWhitespace ); - $wgLanguages->outputMessagesList( $messagesWithWhitespace, $code, "\n$messagesWithWhitespaceNumber messages of $messagesNumber in $code have a trailing whitespace:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $messagesWithWhitespace, $code, "\n$messagesWithWhitespaceNumber messages of $messagesNumber in $code have a trailing whitespace:", $displayLevel, $links, $wikiLanguage ); + $problems += $messagesWithWhitespaceNumber; } # Non-XHTML messages - if ( in_array( 'xhtml', $wgChecks ) ) { - $nonXHTMLMessages = $wgLanguages->getNonXHTMLMessages( $code ); + if ( in_array( 'xhtml', $checks ) ) { + $nonXHTMLMessages = $languages->getNonXHTMLMessages( $code ); $nonXHTMLMessagesNumber = count( $nonXHTMLMessages ); - $wgLanguages->outputMessagesList( $nonXHTMLMessages, $code, "\n$nonXHTMLMessagesNumber messages of $messagesNumber in $code are not well-formed XHTML:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $nonXHTMLMessages, $code, "\n$nonXHTMLMessagesNumber messages of $messagesNumber in $code are not well-formed XHTML:", $displayLevel, $links, $wikiLanguage ); + $problems += $nonXHTMLMessagesNumber; } # Messages with wrong characters - if ( in_array( 'chars', $wgChecks ) ) { - $messagesWithWrongChars = $wgLanguages->getMessagesWithWrongChars( $code ); + if ( in_array( 'chars', $checks ) ) { + $messagesWithWrongChars = $languages->getMessagesWithWrongChars( $code ); $messagesWithWrongCharsNumber = count( $messagesWithWrongChars ); - $wgLanguages->outputMessagesList( $messagesWithWrongChars, $code, "\n$messagesWithWrongCharsNumber messages of $messagesNumber in $code include hidden chars which should not be used in the messages:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + $languages->outputMessagesList( $messagesWithWrongChars, $code, "\n$messagesWithWrongCharsNumber messages of $messagesNumber in $code include hidden chars which should not be used in the messages:", $displayLevel, $links, $wikiLanguage ); + $problems += $messagesWithWrongCharsNumber; } - return ($untranslatedMessagesNumber + $duplicateMessagesNumber + $obsoleteMessagesNumber + $messagesWithoutVariablesNumber + $messagesWithoutPluralNumber + $emptyMessagesNumber + $messagesWithWhitespaceNumber + $nonXHTMLMessagesNumber + $messagesWithWrongCharsNumber); + return $problems; } -?> diff --git a/maintenance/language/checkLanguage.php b/maintenance/language/checkLanguage.php index 4ce811c5..42a43c02 100644 --- a/maintenance/language/checkLanguage.php +++ b/maintenance/language/checkLanguage.php @@ -11,7 +11,7 @@ require_once( 'checkLanguage.inc' ); # Show help if ( isset( $options['help'] ) ) { - echo <<<END + echo <<<ENDS Run this script to check a specific language file, or all of them. Parameters: * lang: Language code (default: the installation default language). You can also specify "all" to check all the languages. @@ -38,37 +38,24 @@ Display levels (default: 2): * 2: Show only the headers and the message keys, without the message values. * 3: Show both the headers and the complete messages, with both keys and values. -END; +ENDS; exit(); } -# Get the language code -if ( isset( $options['lang'] ) ) { - $wgCode = $options['lang']; -} else { - $wgCode = $wgContLang->getCode(); -} - -# Get the display level -if ( isset( $options['level'] ) ) { - $wgDisplayLevel = $options['level']; -} else { - $wgDisplayLevel = 2; -} - -# Get the links options +# Get the parameters +$wgCode = isset( $options['lang'] ) ? $options['lang'] : null; +$wgDisplayLevel = isset( $options['level'] ) ? $options['level'] : 2; $wgLinks = isset( $options['links'] ); $wgWikiLanguage = isset( $options['wikilang'] ) ? $options['wikilang'] : 'en'; +$wgCheckEXIF = !isset( $options['noexif'] ); -# Get the checks to do +# Get the checks $wgChecks = array( 'untranslated', 'obsolete', 'variables', 'empty', 'whitespace', 'xhtml', 'chars' ); if ( isset( $options['whitelist'] ) ) { $wgChecks = explode( ',', $options['whitelist'] ); } elseif ( isset( $options['blacklist'] ) ) { $wgChecks = array_diff( $wgChecks, explode( ',', $options['blacklist'] ) ); } - -# Add duplicate and plural options if specified if ( isset( $options['duplicate'] ) ) { $wgChecks[] = 'duplicate'; } @@ -76,16 +63,9 @@ if ( isset( $options['plural'] ) ) { $wgChecks[] = 'plural'; } -# Should check for EXIF? -$wgCheckEXIF = !isset( $options['noexif'] ); - -# Get language objects +# Get language object $wgLanguages = new languages( $wgCheckEXIF ); -# Get the general messages -$wgGeneralMessages = $wgLanguages->getGeneralMessages(); -$wgRequiredMessagesNumber = count( $wgGeneralMessages['required'] ); - # Check the language if ( $wgCode == 'all' ) { foreach ( $wgLanguages->getLanguages() as $language ) { @@ -94,14 +74,12 @@ if ( $wgCode == 'all' ) { } } } else { - # Can't check English + # Can't check English or English RTL if ( $wgCode == 'en' ) { echo "Current selected language is English, which cannot be checked.\n"; } else if ( $wgCode == 'enRTL' ) { echo "Current selected language is RTL English, which cannot be checked.\n"; } else { - checkLanguage( $wgLanguages, $wgCode ); + checkLanguage( $wgLanguages, $wgCode, $wgDisplayLevel, $wgLinks, $wgWikiLanguage, $wgChecks ); } } - -?> diff --git a/maintenance/language/date-formats.php b/maintenance/language/date-formats.php index a0d46f02..1efa84b5 100644 --- a/maintenance/language/date-formats.php +++ b/maintenance/language/date-formats.php @@ -43,4 +43,4 @@ foreach ( glob( "$IP/languages/messages/Messages*.php" ) as $filename ) { print "\n\n"; } -?> + diff --git a/maintenance/language/diffLanguage.php b/maintenance/language/diffLanguage.php index ada4db07..05a6e4b1 100644 --- a/maintenance/language/diffLanguage.php +++ b/maintenance/language/diffLanguage.php @@ -156,4 +156,4 @@ foreach($referenceMessages as $index => $ref) echo "\n----\n".$msg; echo "$referenceLanguage language is complete at ".number_format((100 - $i/count($wgAllMessagesEn) * 100),2)."%\n"; echo "$i unlocalised messages of the ".count($wgAllMessagesEn)." messages available.\n"; -?> + diff --git a/maintenance/language/digit2html.php b/maintenance/language/digit2html.php new file mode 100644 index 00000000..3b690461 --- /dev/null +++ b/maintenance/language/digit2html.php @@ -0,0 +1,24 @@ +<?php +require( '../commandLine.inc' ); + +# A list of unicode numerals is available at: +# http://www.fileformat.info/info/unicode/category/Nd/list.htm +$langs = array( 'Ar', 'As', 'Bh', 'Bo', 'Dz', 'Fa', 'Gu', 'Hi', 'Km', 'Kn', 'Ks', 'Lo', 'Ml', 'Mr', 'Ne', 'New', 'Or', 'Pa', 'Pi', 'Sa' ); + +foreach( $langs as $code ) { + $filename = Language::getMessagesFileName( $code ); + echo "Loading language [$code] ... "; + unset( $digitTransformTable ); + require_once( $filename ); + if( !isset( $digitTransformTable ) ) { + print "\$digitTransformTable not found\n"; + continue; + } + + print "OK\n\$digitTransformTable = array(\n"; + foreach( $digitTransformTable as $latin => $translation ) { + $htmlent = utf8ToHexSequence( $translation ); + print "'$latin' => '$translation', # &#x$htmlent;\n"; + } + print ");\n"; +} diff --git a/maintenance/language/dumpMessages.php b/maintenance/language/dumpMessages.php index 6b7fea68..e57bfeec 100644 --- a/maintenance/language/dumpMessages.php +++ b/maintenance/language/dumpMessages.php @@ -16,4 +16,4 @@ foreach ( $wgEnglishMessages as $key ) print "MediaWiki $wgVersion language file\n"; print serialize( $messages ); -?> + diff --git a/maintenance/language/function-list.php b/maintenance/language/function-list.php index 84efb29d..67bcab03 100644 --- a/maintenance/language/function-list.php +++ b/maintenance/language/function-list.php @@ -41,4 +41,4 @@ foreach ( $classes as $class ) { print "$numRemoved will be removed out of $total\n"; -?> + diff --git a/maintenance/language/lang2po.php b/maintenance/language/lang2po.php index 9a542e94..0ea3faaa 100644 --- a/maintenance/language/lang2po.php +++ b/maintenance/language/lang2po.php @@ -144,4 +144,4 @@ foreach ( $langTool->getLanguages() as $langcode) { applyPot($langcode); } } -?> + diff --git a/maintenance/language/langmemusage.php b/maintenance/language/langmemusage.php index 54b6a58c..929976d3 100644 --- a/maintenance/language/langmemusage.php +++ b/maintenance/language/langmemusage.php @@ -27,4 +27,4 @@ foreach ( $langtool->getLanguages() as $langcode ) { $memend = memory_get_usage(); echo ' Total Usage: '.($memend - $memstart)."\n"; -?> + diff --git a/maintenance/language/messageTypes.inc b/maintenance/language/messageTypes.inc index 59ddcd95..21734eb3 100644 --- a/maintenance/language/messageTypes.inc +++ b/maintenance/language/messageTypes.inc @@ -44,6 +44,8 @@ $wgIgnoredMessages = array( 'accesskey-feed-atom', 'accesskey-t-contributions', 'accesskey-t-emailuser', + 'accesskey-t-permalink', + 'accesskey-t-print', 'accesskey-t-upload', 'accesskey-t-specialpages', 'accesskey-ca-nstab-main', @@ -62,6 +64,7 @@ $wgIgnoredMessages = array( 'accesskey-diff', 'accesskey-compareselectedversions', 'accesskey-watch', + 'accesskey-upload', 'addsection', 'anonnotice', 'autoblock_whitelist', @@ -76,6 +79,7 @@ $wgIgnoredMessages = array( 'loginlanguagelinks', 'markaspatrolledlink', 'newarticletextanon', + 'newsectionheaderdefaultlevel', 'newtalkseperator', 'noarticletextanon', 'number_of_watching_users_RCview', @@ -83,8 +87,8 @@ $wgIgnoredMessages = array( 'patrol-log-header', 'pubmedurl', 'randompage-url', - 'rc-change-size', 'recentchanges-url', + 'revision-info-current', 'revision-nav', 'rfcurl', 'shareddescriptionfollows', @@ -98,13 +102,13 @@ $wgIgnoredMessages = array( 'talkpagetext', 'trackback', 'trackbackexcerpt', - 'widthheight', ); /** Optional messages, which may be translated only if changed in the other language. */ $wgOptionalMessages = array( 'imgmultigotopost', 'linkprefix', + 'editsection-brackets', 'feed-atom', 'feed-rss', 'sectionlink', @@ -123,11 +127,13 @@ $wgOptionalMessages = array( 'uncategorizedpages-summary', 'uncategorizedcategories-summary', 'uncategorizedimages-summary', + 'uncategorizedtemplates-summary', 'popularpages-summary', 'wantedcategories-summary', 'wantedpages-summary', 'mostlinked-summary', 'mostlinkedcategories-summary', + 'mostlinkedtemplates-summary', 'mostcategories-summary', 'mostimages-summary', 'mostrevisions-summary', @@ -145,7 +151,6 @@ $wgOptionalMessages = array( 'doubleredirects-summary', 'lonelypages-summary', 'unusedtemplates-summary', - 'recentchangeslinked-summary', 'fewestrevisions-summary', 'withoutinterwiki-summary', 'variantname-zh-cn', @@ -162,6 +167,43 @@ $wgOptionalMessages = array( 'variantname-kk-kz', 'variantname-kk-cn', 'variantname-kk', + 'variantname-ku-latn', + 'variantname-ku-arab', + 'variantname-ku', + 'rc-change-size', + 'resetpass_text', + 'widthheight', + 'exif-fnumber-format', + 'exif-focallength-format', + 'exif-compression-6', + 'exif-photometricinterpretation-2', + 'exif-photometricinterpretation-6', + 'exif-xyresolution-i', + 'exif-xyresolution-c', + 'exif-colorspace-1', + 'exif-colorspace-ffff.h', + 'exif-componentsconfiguration-1', + 'exif-componentsconfiguration-2', + 'exif-componentsconfiguration-3', + 'exif-componentsconfiguration-4', + 'exif-componentsconfiguration-5', + 'exif-componentsconfiguration-6', + 'exif-lightsource-20', + 'exif-lightsource-21', + 'exif-lightsource-22', + 'exif-lightsource-23', + 'exif-filesource-3', + 'booksources-isbn', + 'isbn', + 'sp-contributions-explain', + 'sorbs', + 'video-dims', + 'seconds-abbrev', + 'minutes-abbrev', + 'hours-abbrev', + 'filerevert-backlink', + 'filedelete-backlink', + 'pagetitle', ); /** EXIF messages, which may be set as optional in several checks, but are generally mandatory */ @@ -214,7 +256,6 @@ $wgEXIFMessages = array( 'exif-exposuretime', 'exif-exposuretime-format', 'exif-fnumber', - 'exif-fnumber-format', 'exif-exposureprogram', 'exif-spectralsensitivity', 'exif-isospeedratings', @@ -229,7 +270,6 @@ $wgEXIFMessages = array( 'exif-lightsource', 'exif-flash', 'exif-focallength', - 'exif-focallength-format', 'exif-subjectarea', 'exif-flashenergy', 'exif-spatialfrequencyresponse', @@ -287,10 +327,7 @@ $wgEXIFMessages = array( 'exif-gpsdatestamp', 'exif-gpsdifferential', 'exif-compression-1', - 'exif-compression-6', 'exif-unknowndate', - 'exif-photometricinterpretation-2', - 'exif-photometricinterpretation-6', 'exif-orientation-1', 'exif-orientation-2', 'exif-orientation-3', @@ -301,17 +338,7 @@ $wgEXIFMessages = array( 'exif-orientation-8', 'exif-planarconfiguration-1', 'exif-planarconfiguration-2', - 'exif-xyresolution-i', - 'exif-xyresolution-c', - 'exif-colorspace-1', - 'exif-colorspace-ffff.h', 'exif-componentsconfiguration-0', - 'exif-componentsconfiguration-1', - 'exif-componentsconfiguration-2', - 'exif-componentsconfiguration-3', - 'exif-componentsconfiguration-4', - 'exif-componentsconfiguration-5', - 'exif-componentsconfiguration-6', 'exif-exposureprogram-0', 'exif-exposureprogram-1', 'exif-exposureprogram-2', @@ -345,10 +372,6 @@ $wgEXIFMessages = array( 'exif-lightsource-17', 'exif-lightsource-18', 'exif-lightsource-19', - 'exif-lightsource-20', - 'exif-lightsource-21', - 'exif-lightsource-22', - 'exif-lightsource-23', 'exif-lightsource-24', 'exif-lightsource-255', 'exif-focalplaneresolutionunit-2', @@ -359,7 +382,6 @@ $wgEXIFMessages = array( 'exif-sensingmethod-5', 'exif-sensingmethod-7', 'exif-sensingmethod-8', - 'exif-filesource-3', 'exif-scenetype-1', 'exif-customrendered-0', 'exif-customrendered-1', @@ -404,5 +426,3 @@ $wgEXIFMessages = array( 'exif-gpsdirection-t', 'exif-gpsdirection-m', ); - -?> diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index c4e8ee89..00763033 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -118,6 +118,7 @@ $wgMessageStructure = array( 'category_header', 'subcategories', 'category-media-header', + 'category-empty', ), 'mainpage' => array( 'linkprefix', @@ -247,7 +248,10 @@ $wgMessageStructure = array( 'youhavenewmessages', 'newmessageslink', 'newmessagesdifflink', + 'youhavenewmessagesmulti', + 'newtalkseperator', 'editsection', + 'editsection-brackets', 'editold', 'editsectionhint', 'toc', @@ -262,6 +266,7 @@ $wgMessageStructure = array( 'feed-rss', 'sitenotice', 'anonnotice', + 'newsectionheaderdefaultlevel', ), 'nstab' => array( 'nstab-main', @@ -296,10 +301,13 @@ $wgMessageStructure = array( 'missingarticle', 'readonly_lag', 'internalerror', + 'internalerror_info', 'filecopyerror', 'filerenameerror', 'filedeleteerror', + 'directorycreateerror', 'filenotfound', + 'fileexistserror', 'unexpected', 'formerror', 'badarticleerror', @@ -307,7 +315,6 @@ $wgMessageStructure = array( 'badtitle', 'badtitletext', 'perfdisabled', - 'perfdisabledsub', 'perfcached', 'perfcachedts', 'querypage-no-updates', @@ -320,6 +327,9 @@ $wgMessageStructure = array( 'editinginterface', 'sqlhidden', 'cascadeprotected', + 'namespaceprotected', + 'customcssjsprotected', + 'ns-specialprotected', ), 'login' => array( 'logouttitle', @@ -333,7 +343,6 @@ $wgMessageStructure = array( 'yourdomainname', 'externaldberror', 'loginproblem', - 'alreadyloggedin', 'login', 'loginprompt', 'userlogin', @@ -356,8 +365,8 @@ $wgMessageStructure = array( 'yourvariant', 'yournick', 'badsig', + 'badsiglength', 'email', - 'prefs-help-email-enotif', 'prefs-help-realname', 'loginerror', 'prefs-help-email', @@ -371,6 +380,7 @@ $wgMessageStructure = array( 'nouserspecified', 'wrongpassword', 'wrongpasswordempty', + 'passwordtooshort', 'mailmypassword', 'passwordremindertitle', 'passwordremindertext', @@ -390,6 +400,8 @@ $wgMessageStructure = array( 'invalidemailaddress', 'accountcreated', 'accountcreatedtext', + 'loginlanguagelabel', + 'loginlanguagelinks', ), 'resetpass' => array( 'resetpass', @@ -442,6 +454,7 @@ $wgMessageStructure = array( 'subject-preview', 'blockedtitle', 'blockedtext', + 'autoblockedtext', 'blockedoriginalsource', 'blockededitsource', 'whitelistedittitle', @@ -477,7 +490,7 @@ $wgMessageStructure = array( 'previewconflict', 'session_fail_preview', 'session_fail_preview_html', - 'importing', + 'token_suffix_mismatch', 'editing', 'editinguser', 'editingsection', @@ -505,6 +518,10 @@ $wgMessageStructure = array( 'edittools', 'nocreatetitle', 'nocreatetext', + 'nocreate-loggedin', + 'permissionserrors', + 'permissionserrorstext', + 'recreate-deleted-warn', ), 'undo' => array( 'undo-success', @@ -525,6 +542,7 @@ $wgMessageStructure = array( 'currentrev', 'revisionasof', 'revision-info', + 'revision-info-current', 'revision-nav', 'previousrevision', 'nextrevision', @@ -600,9 +618,6 @@ $wgMessageStructure = array( 'searchresulttext', 'searchsubtitle', 'searchsubtitleinvalid', - 'badquery', - 'badquerytext', - 'matchtotals', 'noexactmatch', 'titlematches', 'notitlematches', @@ -618,12 +633,12 @@ $wgMessageStructure = array( 'powersearchtext', 'searchdisabled', 'googlesearch', - 'blanknamespace', ), 'preferences' => array( 'preferences', 'preferences-summary', 'mypreferences', + 'prefs-edits', 'prefsnologin', 'prefsnologintext', 'prefsreset', @@ -666,7 +681,7 @@ $wgMessageStructure = array( 'resultsperpage', 'contextlines', 'contextchars', - 'stubthreshold', + 'stub-threshold', 'recentchangesdays', 'recentchangescount', 'savedprefs', @@ -691,20 +706,26 @@ $wgMessageStructure = array( 'userrights-groupsavailable', 'userrights-groupshelp', 'userrights-reason', + 'userrights-available-none', + 'userrights-available-add', + 'userrights-available-remove', ), 'group' => array( 'group', + 'group-autoconfirmed', 'group-bot', 'group-sysop', 'group-bureaucrat', 'group-all', ), 'group-member' => array( + 'group-autoconfirmed-member', 'group-bot-member', 'group-sysop-member', 'group-bureaucrat-member', ), 'grouppage' => array( + 'grouppage-autoconfirmed', 'grouppage-bot', 'grouppage-sysop', 'grouppage-bureaucrat', @@ -744,9 +765,11 @@ $wgMessageStructure = array( 'rc_categories', 'rc_categories_any', 'rc-change-size', + 'newsectionsummary', ), 'recentchangeslinked' => array( 'recentchangeslinked', + 'recentchangeslinked-title', 'recentchangeslinked-noresult', 'recentchangeslinked-summary', ), @@ -771,7 +794,7 @@ $wgMessageStructure = array( 'uploadedfiles', 'ignorewarning', 'ignorewarnings', - 'minlength', + 'minlength1', 'illegalfilename', 'badfilename', 'filetype-badmime', @@ -788,10 +811,10 @@ $wgMessageStructure = array( 'fileexists-forbidden', 'fileexists-shared-forbidden', 'successfulupload', - 'fileuploaded', 'uploadwarning', 'savefile', 'uploadedimage', + 'overwroteimage', 'uploaddisabled', 'uploaddisabledtext', 'uploadscripted', @@ -820,6 +843,7 @@ $wgMessageStructure = array( 'license', 'nolicense', 'licenses', + 'license-nopreview', 'upload_source_url', 'upload_source_file', ), @@ -827,7 +851,6 @@ $wgMessageStructure = array( 'imagelist', 'imagelist-summary', 'imagelisttext', - 'imagelistforuser', 'getimagelist', 'ilsubmit', 'showlast', @@ -837,12 +860,17 @@ $wgMessageStructure = array( 'imgdelete', 'imgdesc', 'imgfile', - 'imglegend', - 'imghistory', - 'revertimg', - 'deleteimg', - 'deleteimgcompletely', - 'imghistlegend', + 'filehist', + 'filehist-help', + 'filehist-deleteall', + 'filehist-deleteone', + 'filehist-revert', + 'filehist-current', + 'filehist-datetime', + 'filehist-user', + 'filehist-dimensions', + 'filehist-filesize', + 'filehist-comment', 'imagelinks', 'linkstoimage', 'nolinkstoimage', @@ -860,6 +888,31 @@ $wgMessageStructure = array( 'imagelist_description', 'imagelist_search_for', ), + 'filerevert' => array( + 'filerevert', + 'filerevert-backlink', + 'filerevert-legend', + 'filerevert-intro', + 'filerevert-comment', + 'filerevert-defaultcomment', + 'filerevert-submit', + 'filerevert-success', + 'filerevert-badversion', + ), + 'filedelete' => array( + 'filedelete', + 'filedelete-backlink', + 'filedelete-legend', + 'filedelete-intro', + 'filedelete-intro-old', + 'filedelete-comment', + 'filedelete-submit', + 'filedelete-success', + 'filedelete-success-old', + 'filedelete-nofile', + 'filedelete-nofile-old', + 'filedelete-iscurrent', + ), 'mimesearch' => array( 'mimesearch', 'mimesearch-summary', @@ -938,6 +991,8 @@ $wgMessageStructure = array( 'uncategorizedcategories-summary', 'uncategorizedimages', 'uncategorizedimages-summary', + 'uncategorizedtemplates', + 'uncategorizedtemplates-summary', 'unusedcategories', 'unusedimages', 'popularpages', @@ -950,6 +1005,8 @@ $wgMessageStructure = array( 'mostlinked-summary', 'mostlinkedcategories', 'mostlinkedcategories-summary', + 'mostlinkedtemplates', + 'mostlinkedtemplates-summary', 'mostcategories', 'mostcategories-summary', 'mostimages', @@ -1016,6 +1073,7 @@ $wgMessageStructure = array( 'specialloguserlabel', 'speciallogtitlelabel', 'log', + 'all-logs-page', 'log-search-legend', 'log-search-submit', 'alllogstext', @@ -1034,6 +1092,7 @@ $wgMessageStructure = array( 'allpagessubmit', 'allpagesprefix', 'allpagesbadtitle', + 'allpages-bad-ns', ), 'listusers' => array( 'listusersfrom', @@ -1066,11 +1125,6 @@ $wgMessageStructure = array( 'watchlistfor', 'nowatchlist', 'watchlistanontext', - 'watchlistcount', - 'clearwatchlist', - 'watchlistcleartext', - 'watchlistclearbutton', - 'watchlistcleardone', 'watchnologin', 'watchnologintext', 'addedwatch', @@ -1083,27 +1137,21 @@ $wgMessageStructure = array( 'unwatchthispage', 'notanarticle', 'watchnochange', - 'watchdetails', + 'watchlist-details', 'wlheader-enotif', 'wlheader-showupdated', 'watchmethod-recent', 'watchmethod-list', - 'removechecked', 'watchlistcontains', - 'watcheditlist', - 'removingchecked', - 'couldntremove', 'iteminvalidname', 'wlnote', 'wlshowlast', - 'wlsaved', 'watchlist-show-bots', 'watchlist-hide-bots', 'watchlist-show-own', 'watchlist-hide-own', 'watchlist-show-minor', 'watchlist-hide-minor', - 'wldone', ), 'watching' => array( 'watching', @@ -1113,10 +1161,13 @@ $wgMessageStructure = array( 'enotif_mailer', 'enotif_reset', 'enotif_newpagetext', + 'enotif_impersonal_salutation', 'changed', 'created', 'enotif_subject', 'enotif_lastvisited', + 'enotif_lastdiff', + 'enotif_anon_editor', 'enotif_body', ), 'deleteprotectrev' => array( @@ -1138,7 +1189,6 @@ $wgMessageStructure = array( 'deletionlog', 'reverted', 'deletecomment', - 'imagereverted', 'rollback', 'rollback_short', 'rollbacklink', @@ -1147,23 +1197,20 @@ $wgMessageStructure = array( 'alreadyrolled', 'editcomment', 'revertpage', + 'rollback-success', 'sessionfailure', 'protectlogpage', 'protectlogtext', 'protectedarticle', + 'modifiedarticleprotection', 'unprotectedarticle', 'protectsub', - 'confirmprotecttext', 'confirmprotect', - 'protectmoveonly', 'protectcomment', 'protectexpiry', 'protect_expiry_invalid', 'protect_expiry_old', 'unprotectsub', - 'confirmunprotecttext', - 'confirmunprotect', - 'unprotectcomment', 'protect-unchain', 'protect-text', 'protect-locked-blocked', @@ -1171,6 +1218,7 @@ $wgMessageStructure = array( 'protect-locked-access', 'protect-cascadeon', 'protect-default', + 'protect-fallback', 'protect-level-autoconfirmed', 'protect-level-sysop', 'protect-summary-cascade', @@ -1179,6 +1227,8 @@ $wgMessageStructure = array( 'restriction-type', 'restriction-level', 'minimum-size', + 'maximum-size', + 'pagesize', ), 'restrictions' => array( 'restriction-edit', @@ -1215,10 +1265,17 @@ $wgMessageStructure = array( 'undelete-search-prefix', 'undelete-search-submit', 'undelete-no-results', + 'undelete-filename-mismatch', + 'undelete-bad-store-key', + 'undelete-cleanup-error', + 'undelete-missing-filearchive', + 'undelete-error-short', + 'undelete-error-long', ), 'nsform' => array( 'namespace', 'invert', + 'blanknamespace', ), 'contributions' => array( 'contributions', @@ -1228,6 +1285,8 @@ $wgMessageStructure = array( 'ucnote', 'uclinks', 'uctop', + 'month', + 'year', ), 'sp-contributions' => array( 'sp-contributions-newest', @@ -1240,6 +1299,7 @@ $wgMessageStructure = array( 'sp-contributions-search', 'sp-contributions-username', 'sp-contributions-submit', + 'sp-contributions-explain', 'sp-contributions-footer', 'sp-contributions-footer-anon', ), @@ -1248,6 +1308,7 @@ $wgMessageStructure = array( ), 'whatlinkshere' => array( 'whatlinkshere', + 'whatlinkshere-title', 'whatlinkshere-summary', 'whatlinkshere-barrow', 'notargettitle', @@ -1260,6 +1321,7 @@ $wgMessageStructure = array( 'istemplate', 'whatlinkshere-prev', 'whatlinkshere-next', + 'whatlinkshere-links', ), 'block' => array( 'blockip', @@ -1272,6 +1334,7 @@ $wgMessageStructure = array( 'ipbreason-dropdown', 'ipbanononly', 'ipbcreateaccount', + 'ipbemailban', 'ipbenableautoblock', 'ipbsubmit', 'ipbother', @@ -1291,7 +1354,10 @@ $wgMessageStructure = array( 'unblockiptext', 'ipusubmit', 'unblocked', + 'unblocked-id', 'ipblocklist', + 'ipblocklist-legend', + 'ipblocklist-username', 'ipblocklist-summary', 'ipblocklist-submit', 'blocklistline', @@ -1300,7 +1366,9 @@ $wgMessageStructure = array( 'anononlyblock', 'noautoblockblock', 'createaccountblock', - 'ipblocklistempty', + 'emailblock', + 'ipblocklist-empty', + 'ipblocklist-no-results', 'blocklink', 'unblocklink', 'contribslink', @@ -1312,6 +1380,7 @@ $wgMessageStructure = array( 'block-log-flags-anononly', 'block-log-flags-nocreate', 'block-log-flags-noautoblock', + 'block-log-flags-noemail', 'range_block_disabled', 'ipb_expiry_invalid', 'ipb_already_blocked', @@ -1348,11 +1417,12 @@ $wgMessageStructure = array( 'movearticle', 'movenologin', 'movenologintext', + 'movenotallowed', 'newtitle', 'move-watch', 'movepagebtn', 'pagemovedsub', - 'pagemovedtext', + 'movepage-moved', 'articleexists', 'talkexists', 'movedto', @@ -1380,6 +1450,7 @@ $wgMessageStructure = array( 'export-submit', 'export-addcattext', 'export-addcat', + 'export-download', ), 'allmessages' => array( 'allmessages', @@ -1387,7 +1458,6 @@ $wgMessageStructure = array( 'allmessagesdefault', 'allmessagescurrent', 'allmessagestext', - 'allmessagesnotsupportedUI', 'allmessagesnotsupportedDB', 'allmessagesfilter', 'allmessagesmodified', @@ -1469,6 +1539,8 @@ $wgMessageStructure = array( 'accesskey-feed-atom', 'accesskey-t-contributions', 'accesskey-t-emailuser', + 'accesskey-t-permalink', + 'accesskey-t-print', 'accesskey-t-upload', 'accesskey-t-specialpages', 'accesskey-ca-nstab-main', @@ -1487,6 +1559,7 @@ $wgMessageStructure = array( 'accesskey-diff', 'accesskey-compareselectedversions', 'accesskey-watch', + 'accesskey-upload', ), 'tooltips' => array( 'tooltip-pt-userpage', @@ -1527,6 +1600,8 @@ $wgMessageStructure = array( 'tooltip-t-emailuser', 'tooltip-t-upload', 'tooltip-t-specialpages', + 'tooltip-t-print', + 'tooltip-t-permalink', 'tooltip-ca-nstab-main', 'tooltip-ca-nstab-user', 'tooltip-ca-nstab-media', @@ -1544,6 +1619,7 @@ $wgMessageStructure = array( 'tooltip-compareselectedversions', 'tooltip-watch', 'tooltip-recreate', + 'tooltip-upload', ), 'stylesheets' => array( 'common.css', @@ -1618,6 +1694,12 @@ $wgMessageStructure = array( ), 'imagedeletion' => array( 'deletedrevision', + 'filedeleteerror-short', + 'filedeleteerror-long', + 'filedelete-missing', + 'filedelete-old-unregistered', + 'filedelete-current-unregistered', + 'filedelete-archive-read-only', ), 'browsediffs' => array( 'previousdiff', @@ -1628,10 +1710,11 @@ $wgMessageStructure = array( 'imagemaxsize', 'thumbsize', 'widthheight', + 'widthheightpage', 'file-info', 'file-info-size', 'file-nohires', - 'file-svg', + 'svg-long-desc', 'show-big-image', 'show-big-image-thumb', ), @@ -1641,6 +1724,15 @@ $wgMessageStructure = array( 'showhidebots', 'noimages', ), + 'video-info' => array( + 'video-dims', + 'seconds-abbrev', + 'minutes-abbrev', + 'hours-abbrev', + ), + 'badimagelist' => array( + 'bad_image_list', + ), 'variantname-zh' => array( 'variantname-zh-cn', 'variantname-zh-tw', @@ -1661,8 +1753,10 @@ $wgMessageStructure = array( 'variantname-kk-cn', 'variantname-kk', ), - 'passwordtooshort' => array( - 'passwordtooshort', + 'variantname-ku' => array( + 'variantname-ku-arab', + 'variantname-ku-latn', + 'variantname-ku', ), 'metadata' => array( 'metadata', @@ -1984,9 +2078,9 @@ $wgMessageStructure = array( 'all' => array( 'recentchangesall', 'imagelistall', - 'watchlistall1', 'watchlistall2', 'namespacesall', + 'monthsall', ), 'confirmemail' => array( 'confirmemail', @@ -2005,11 +2099,6 @@ $wgMessageStructure = array( 'confirmemail_subject', 'confirmemail_body', ), - 'inputbox' => array( - 'tryexact', - 'searchfulltext', - 'createarticle', - ), 'scarytransclusion' => array( 'scarytranscludedisabled', 'scarytranscludefailed', @@ -2038,26 +2127,15 @@ $wgMessageStructure = array( 'confirm_purge', 'confirm_purge_button', ), - 'newmessagesmulti' => array( - 'youhavenewmessagesmulti', - 'newtalkseperator', - ), 'search2' => array( 'searchcontaining', 'searchnamed', 'articletitles', 'hideresults', ), - 'displaytitle' => array( - 'displaytitle', - ), 'catseparator' => array( 'catseparator', ), - 'loginlanguage' => array( - 'loginlanguagelabel', - 'loginlanguagelinks', - ), 'imgmulti' => array( 'imgmultipageprev', 'imgmultipagenext', @@ -2098,6 +2176,38 @@ $wgMessageStructure = array( 'livepreview-failed', 'livepreview-error', ), + 'lagwarning' => array( + 'lag-warn-normal', + 'lag-warn-high', + ), + 'watchlisteditor' => array( + 'watchlistedit-numitems', + 'watchlistedit-noitems', + 'watchlistedit-clear-title', + 'watchlistedit-clear-legend', + 'watchlistedit-clear-confirm', + 'watchlistedit-clear-submit', + 'watchlistedit-clear-done', + 'watchlistedit-normal-title', + 'watchlistedit-normal-legend', + 'watchlistedit-normal-explain', + 'watchlistedit-normal-submit', + 'watchlistedit-normal-done', + 'watchlistedit-raw-title', + 'watchlistedit-raw-legend', + 'watchlistedit-raw-explain', + 'watchlistedit-raw-titles', + 'watchlistedit-raw-submit', + 'watchlistedit-raw-done', + 'watchlistedit-raw-added', + 'watchlistedit-raw-removed', + ), + 'watchlisttools' => array( + 'watchlisttools-view', + 'watchlisttools-edit', + 'watchlisttools-raw', + 'watchlisttools-clear', + ), ); /** Comments for each block */ $wgBlockComments = array( @@ -2148,6 +2258,8 @@ XHTML id names.", 'upload-curl-errors' => 'Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>', 'licenses' => '', 'imagelist' => 'Image list', + 'filerevert' => 'File reversion', + 'filedelete' => 'File deletion', 'mimesearch' => 'MIME search', 'unwatchedpages' => 'Unwatched pages', 'listredirects' => 'List redirects', @@ -2199,14 +2311,16 @@ XHTML id names.", 'patrol-log' => 'Patrol log', 'imagedeletion' => 'Image deletion', 'browsediffs' => 'Browsing diffs', - 'newimages' => '', + 'newimages' => 'Special:Newimages', + 'video-info' => 'Video information, used by Language::formatTimePeriod() to format lengths in the above messages', + 'badimagelist' => 'Bad image list', 'variantname-zh' => "Short names for language variants used for language conversion links. To disable showing a particular link, set it to 'disable', e.g. 'variantname-zh-sg' => 'disable', Variants for Chinese language", 'variantname-sr' => 'Variants for Serbian language', 'variantname-kk' => 'Variants for Kazakh language', - 'passwordtooshort' => '', + 'variantname-ku' => 'Variants for Kurdish language', 'media-info' => 'Media information', 'metadata' => 'Metadata', 'exif' => 'EXIF tags', @@ -2245,31 +2359,29 @@ Variants for Chinese language", 'edit-externally' => 'External editor support', 'all' => "'all' in various places, this might be different for inflected languages", 'confirmemail' => 'E-mail address confirmation', - 'inputbox' => 'Inputbox extension, may be useful in other contexts as well', 'scarytransclusion' => 'Scary transclusion', 'trackbacks' => 'Trackbacks', 'deleteconflict' => 'Delete conflict', 'unit-pixel' => '', 'htmldump' => 'HTML dump', 'purge' => 'action=purge', - 'newmessagesmulti' => '', - 'search2' => '', - 'displaytitle' => 'DISPLAYTITLE', + 'search2' => 'AJAX search', 'catseparator' => 'Separator for categories in page lists', - 'loginlanguage' => '', 'imgmulti' => 'Multipage image navigation', 'tablepager' => 'Table pager', 'autosumm' => 'Auto-summaries', 'autoblock_whitelist' => 'Autoblock whitelist', 'sizeunits' => 'Size units', 'livepreview' => 'Live preview', + 'lagwarning' => 'Friendlier slave lag warnings', + 'watchlisteditor' => 'Watchlist editor', + 'watchlisttools' => 'Watchlist editing tools', ); /** Short comments for standalone messages */ $wgMessageComments = array( 'lastmodifiedat' => '$1 date, $2 time', 'sitenotice' => 'the equivalent to wgSiteNotice', - 'perfdisabledsub' => 'obsolete?', 'history-feed-item-nocomment' => 'user at time', 'editcomment' => 'only shown if there is an edit comment', 'lastmodifiedatby' => '$1 date, $2 time, $3 user', @@ -2281,7 +2393,7 @@ $wgMessageComments = array( 'exif-orientation-6' => '0th row: right; 0th column: top', 'exif-orientation-7' => '0th row: right; 0th column: bottom', 'exif-orientation-8' => '0th row: left; 0th column: bottom', - 'autoredircomment' => 'This should be changed to the new naming convention, but existed beforehand', + 'movepage-moved' => 'The two titles are passed in plain text as $3 and $4 to allow additional goodies in the message.' ); /** Messages which contain dollar signs (which are not followed by numbers), and therefore should use a single apostrophe */ @@ -2291,5 +2403,3 @@ $wgMessagseWithDollarSigns = array( 'enotif_body', 'allmessagesnotsupportedDB', ); - -?> diff --git a/maintenance/language/rebuildLanguage.php b/maintenance/language/rebuildLanguage.php index d4753c4a..304f8b5c 100644 --- a/maintenance/language/rebuildLanguage.php +++ b/maintenance/language/rebuildLanguage.php @@ -61,4 +61,4 @@ if ( $wgCode == 'all' ) { rebuildLanguage( $wgCode, $wgWriteToFile, $wgListUnknownMessages ); } -?> + diff --git a/maintenance/language/splitLanguageFiles.php b/maintenance/language/splitLanguageFiles.php index 2263e611..d1ce6e7e 100644 --- a/maintenance/language/splitLanguageFiles.php +++ b/maintenance/language/splitLanguageFiles.php @@ -10,4 +10,4 @@ include(dirname(__FILE__).'/../commandLine.inc'); -?> + diff --git a/maintenance/language/transstat.php b/maintenance/language/transstat.php index 36a78000..6a1423a8 100644 --- a/maintenance/language/transstat.php +++ b/maintenance/language/transstat.php @@ -209,4 +209,4 @@ foreach ( $wgLanguages->getLanguages() as $code ) { # Footer $wgOut->footer(); -?> + diff --git a/maintenance/language/validate.php b/maintenance/language/validate.php index 10d98d37..5e96c2d2 100644 --- a/maintenance/language/validate.php +++ b/maintenance/language/validate.php @@ -37,4 +37,4 @@ function getVars( $filename ) { unset( $vars['filename'] ); return $vars; } -?> + diff --git a/maintenance/language/writeMessagesArray.inc b/maintenance/language/writeMessagesArray.inc index 01fc7762..bcbf05ee 100644 --- a/maintenance/language/writeMessagesArray.inc +++ b/maintenance/language/writeMessagesArray.inc @@ -27,13 +27,12 @@ function writeMessagesToFile( $messages, $code, $write, $listUnknown ) { $contents = file_get_contents( $filename ); if ( strpos( $contents, '$messages' ) !== false ) { $contents = explode( '$messages', $contents ); - if ( $messagesText . "\n?>\n" == '$messages' . $contents[1] ) { - echo "Generated messages for language $code. Same to the current file.\n"; + if ( $messagesText == '$messages' . $contents[1] ) { + echo "Generated messages for language $code. Same as the current file.\n"; } else { if ( $write ) { $new = $contents[0]; $new .= $messagesText; - $new .= "\n?>\n"; file_put_contents( $filename, $new ); echo "Generated and wrote messages for language $code.\n"; } else { @@ -74,7 +73,8 @@ function writeMessagesArray( $messages, $ignoredComments = false ) { } # Write all the messages - $messagesText = "\$messages = array(\n"; + $messagesText = "\$messages = array( +"; foreach( $sortedMessages as $block => $messages ) { # Skip if it's the block of unknown messages - handle that in the end of file if ( $block == 'unknown' ) { @@ -86,7 +86,8 @@ function writeMessagesArray( $messages, $ignoredComments = false ) { } ksort( $sortedMessages['unknown'] ); $messagesText .= writeMessagesBlock( 'unknown', 'Unknown messages', $sortedMessages['unknown'], $ignoredComments ); # Write the unknown messages, alphabetically sorted - $messagesText .= ");\n"; + $messagesText .= "); +"; return array( $messagesText, $sortedMessages ); } @@ -114,9 +115,13 @@ function writeMessagesBlock( $name, $comment, $messages, $ignoredComments ) { # Format the block comment (if exists); check for multiple lines comments if ( !empty( $comment ) ) { if ( strpos( $comment, "\n" ) === false ) { - $blockText .= "# $comment\n"; + $blockText .= "# $comment +"; } else { - $blockText .= "/*\n$comment\n*/\n"; + $blockText .= "/* +$comment +*/ +"; } } @@ -172,11 +177,13 @@ function writeMessagesBlock( $name, $comment, $messages, $ignoredComments ) { } # Newline - $blockText .= "\n"; + $blockText .= " +"; } # Newline to end the block - $blockText .= "\n"; + $blockText .= " +"; return $blockText; } diff --git a/maintenance/mcc.php b/maintenance/mcc.php index b0302ab2..97a344fb 100644 --- a/maintenance/mcc.php +++ b/maintenance/mcc.php @@ -8,7 +8,6 @@ /** */ require_once( 'commandLine.inc' ); -require_once( 'memcached-client.php' ); $mcc = new memcached( array('persistant' => true/*, 'debug' => true*/) ); $mcc->set_servers( $wgMemCachedServers ); @@ -173,4 +172,4 @@ do { } } while ( !$quit ); -?> + diff --git a/maintenance/mctest.php b/maintenance/mctest.php index dbf99f62..3ceda8e1 100644 --- a/maintenance/mctest.php +++ b/maintenance/mctest.php @@ -1,5 +1,5 @@ <?php -/* $Id: mctest.php 19364 2007-01-17 00:54:54Z brion $ */ +/* $Id: mctest.php 23531 2007-06-29 01:19:14Z simetrical $ */ $optionsWithArgs = array( 'i' ); @@ -55,4 +55,4 @@ foreach ( $wgMemCachedServers as $server ) { } -?> + diff --git a/maintenance/moveBatch.php b/maintenance/moveBatch.php index 058652dc..f30bb591 100644 --- a/maintenance/moveBatch.php +++ b/maintenance/moveBatch.php @@ -91,4 +91,4 @@ for ( $linenum = 1; !feof( $file ); $linenum++ ) { } -?> + diff --git a/maintenance/namespace2sql.php b/maintenance/namespace2sql.php index 081f6099..94bd9671 100644 --- a/maintenance/namespace2sql.php +++ b/maintenance/namespace2sql.php @@ -11,4 +11,4 @@ for ($i = -2; $i < 16; ++$i) { print "INSERT INTO ns_name(ns_db, ns_num, ns_name) VALUES('$dbname', $i, '$nsname');\n"; } -?> + diff --git a/maintenance/namespaceDupes.php b/maintenance/namespaceDupes.php index c5c1ec58..16796ba3 100644 --- a/maintenance/namespaceDupes.php +++ b/maintenance/namespaceDupes.php @@ -1,5 +1,5 @@ <?php -# Copyright (C) 2005 Brion Vibber <brion@pobox.com> +# Copyright (C) 2005-2007 Brion Vibber <brion@pobox.com> # http://www.mediawiki.org/ # # This program is free software; you can redistribute it and/or modify @@ -21,7 +21,6 @@ $options = array( 'fix', 'suffix', 'help' ); /** */ require_once( 'commandLine.inc' ); -#require_once( 'maintenance/userDupes.inc' ); if(isset( $options['help'] ) ) { print <<<END @@ -30,40 +29,97 @@ usage: namespaceDupes.php [--fix] [--suffix=<text>] [--help] --fix : attempt to automatically fix errors --suffix=<text> : dupes will be renamed with correct namespace with <text> appended after the article name. + --prefix=<text> : Do an explicit check for the given title prefix + in place of the standard namespace list. + --verbose : Display output for checked namespaces without conflicts END; die; } class NamespaceConflictChecker { - function NamespaceConflictChecker( &$db ) { - $this->db =& $db; + function NamespaceConflictChecker( $db, $verbose=false ) { + $this->db = $db; + $this->verbose = $verbose; } function checkAll( $fix, $suffix = '' ) { - global $wgContLang; - $spaces = $wgContLang->getNamespaces(); + global $wgContLang, $wgNamespaceAliases, $wgCanonicalNamespaceNames; + global $wgCapitalLinks; + + $spaces = array(); + + // List interwikis first, so they'll be overridden + // by any conflicting local namespaces. + foreach( $this->getInterwikiList() as $prefix ) { + $name = $wgContLang->ucfirst( $prefix ); + $spaces[$name] = 0; + } + + // Now pull in all canonical and alias namespaces... + foreach( $wgCanonicalNamespaceNames as $ns => $name ) { + // This includes $wgExtraNamespaces + if( $name !== '' ) { + $spaces[$name] = $ns; + } + } + foreach( $wgContLang->getNamespaces() as $ns => $name ) { + if( $name !== '' ) { + $spaces[$name] = $ns; + } + } + foreach( $wgNamespaceAliases as $name => $ns ) { + $spaces[$name] = $ns; + } + foreach( $wgContLang->namespaceAliases as $name => $ns ) { + $spaces[$name] = $ns; + } + + if( !$wgCapitalLinks ) { + // We'll need to check for lowercase keys as well, + // since we're doing case-sensitive searches in the db. + foreach( array_values( $spaces ) as $name => $ns ) { + $lcname = $wgContLang->lcfirst( $name ); + $spaces[$lcname] = $ns; + } + } + ksort( $spaces ); + asort( $spaces ); + $ok = true; - foreach( $spaces as $ns => $name ) { + foreach( $spaces as $name => $ns ) { $ok = $this->checkNamespace( $ns, $name, $fix, $suffix ) && $ok; } return $ok; } + + private function getInterwikiList() { + $result = $this->db->select( 'interwiki', array( 'iw_prefix' ) ); + while( $row = $this->db->fetchObject( $result ) ) { + $prefixes[] = $row->iw_prefix; + } + $this->db->freeResult( $result ); + return $prefixes; + } function checkNamespace( $ns, $name, $fix, $suffix = '' ) { - echo "Checking namespace $ns: \"$name\"\n"; - if( $name == '' ) { - echo "... skipping article namespace\n"; - return true; + if( $ns == 0 ) { + $header = "Checking interwiki prefix: \"$name\"\n"; + } else { + $header = "Checking namespace $ns: \"$name\"\n"; } $conflicts = $this->getConflicts( $ns, $name ); $count = count( $conflicts ); if( $count == 0 ) { - echo "... no conflicts detected!\n"; + if( $this->verbose ) { + echo $header; + echo "... no conflicts detected!\n"; + } return true; } + echo $header; echo "... $count conflicts detected:\n"; $ok = true; foreach( $conflicts as $row ) { @@ -77,7 +133,7 @@ class NamespaceConflictChecker { } /** - * @fixme: do this for reals + * @todo: do this for reals */ function checkPrefix( $key, $prefix, $fix, $suffix = '' ) { echo "Checking prefix \"$prefix\" vs namespace $key\n"; @@ -85,16 +141,23 @@ class NamespaceConflictChecker { } function getConflicts( $ns, $name ) { - $page = $this->newSchema() ? 'page' : 'cur'; + $page = 'page'; $table = $this->db->tableName( $page ); $prefix = $this->db->strencode( $name ); $likeprefix = str_replace( '_', '\\_', $prefix); + $encNamespace = $this->db->addQuotes( $ns ); - $sql = "SELECT {$page}_id AS id, - {$page}_title AS oldtitle, - $ns AS namespace, - TRIM(LEADING '$prefix:' FROM {$page}_title) AS title + $titleSql = "TRIM(LEADING '$prefix:' FROM {$page}_title)"; + if( $ns == 0 ) { + // An interwiki; try an alternate encoding with '-' for ':' + $titleSql = "CONCAT('$prefix-',$titleSql)"; + } + + $sql = "SELECT {$page}_id AS id, + {$page}_title AS oldtitle, + $encNamespace AS namespace, + $titleSql AS title FROM {$table} WHERE {$page}_namespace=0 AND {$page}_title LIKE '$likeprefix:%'"; @@ -134,9 +197,7 @@ class NamespaceConflictChecker { $title = Title::makeTitleSafe( $row->namespace, $row->title ); echo "... *** using suffixed form [[" . $title->getPrefixedText() . "]] ***\n"; } - $tables = $this->newSchema() - ? array( 'page' ) - : array( 'cur', 'old' ); + $tables = array( 'page' ); foreach( $tables as $table ) { $this->resolveConflictOn( $row, $table ); } @@ -160,10 +221,6 @@ class NamespaceConflictChecker { echo "ok.\n"; return true; } - - function newSchema() { - return class_exists( 'Revision' ); - } } @@ -171,12 +228,14 @@ class NamespaceConflictChecker { $wgTitle = Title::newFromText( 'Namespace title conflict cleanup script' ); +$verbose = isset( $options['verbose'] ); $fix = isset( $options['fix'] ); $suffix = isset( $options['suffix'] ) ? $options['suffix'] : ''; $prefix = isset( $options['prefix'] ) ? $options['prefix'] : ''; $key = isset( $options['key'] ) ? intval( $options['key'] ) : 0; + $dbw = wfGetDB( DB_MASTER ); -$duper = new NamespaceConflictChecker( $dbw ); +$duper = new NamespaceConflictChecker( $dbw, $verbose ); if( $prefix ) { $retval = $duper->checkPrefix( $key, $prefix, $fix, $suffix ); @@ -192,4 +251,4 @@ if( $retval ) { exit( -1 ); } -?> + diff --git a/maintenance/nextJobDB.php b/maintenance/nextJobDB.php index 7aa05a27..dfa8d028 100644 --- a/maintenance/nextJobDB.php +++ b/maintenance/nextJobDB.php @@ -4,9 +4,19 @@ * Pick a database that has pending jobs */ +$options = array( 'type' ); + require_once( 'commandLine.inc' ); -$pendingDBs = $wgMemc->get( 'jobqueue:dbs' ); +$type = isset($options['type']) + ? $options['type'] + : false; + +$mckey = $type === false + ? "jobqueue:dbs" + : "jobqueue:dbs:$type"; + +$pendingDBs = $wgMemc->get( $mckey ); if ( !$pendingDBs ) { $pendingDBs = array(); # Cross-reference DBs by master DB server @@ -22,6 +32,7 @@ if ( !$pendingDBs ) { foreach ( $dbsByMaster as $master => $dbs ) { $dbConn = new Database( $master, $wgDBuser, $wgDBpassword ); + $stype = $dbConn->addQuotes($type); # Padding row for MySQL bug $sql = "(SELECT '-------------------------------------------')"; @@ -29,7 +40,10 @@ if ( !$pendingDBs ) { if ( $sql != '' ) { $sql .= ' UNION '; } - $sql .= "(SELECT '$dbName' FROM `$dbName`.job LIMIT 1)"; + if ($type === false) + $sql .= "(SELECT '$dbName' FROM `$dbName`.job LIMIT 1)"; + else + $sql .= "(SELECT '$dbName' FROM `$dbName`.job WHERE job_cmd=$stype LIMIT 1)"; } $res = $dbConn->query( $sql, 'nextJobDB.php' ); $row = $dbConn->fetchRow( $res ); // discard padding row @@ -38,11 +52,11 @@ if ( !$pendingDBs ) { } } - $wgMemc->set( 'jobqueue:dbs', $pendingDBs, 300 ); + $wgMemc->set( $mckey, $pendingDBs, 300 ); } if ( $pendingDBs ) { echo $pendingDBs[mt_rand(0, count( $pendingDBs ) - 1)]; } -?> + diff --git a/maintenance/nukeNS.php b/maintenance/nukeNS.php index 8e280b20..9bf7004b 100644 --- a/maintenance/nukeNS.php +++ b/maintenance/nukeNS.php @@ -105,4 +105,3 @@ function NukeNS($ns_no, $delete) { } -?>
\ No newline at end of file diff --git a/maintenance/nukePage.php b/maintenance/nukePage.php index 6ea9e18a..f1ebe734 100644 --- a/maintenance/nukePage.php +++ b/maintenance/nukePage.php @@ -26,4 +26,3 @@ function ShowUsage() { echo( " <title> : Page title; spaces escaped with underscores\n\n" ); } -?>
\ No newline at end of file diff --git a/maintenance/ora/tables.sql b/maintenance/ora/tables.sql index d2436e1d..6d4b8ed5 100644 --- a/maintenance/ora/tables.sql +++ b/maintenance/ora/tables.sql @@ -226,7 +226,7 @@ CREATE TABLE image ( img_media_type CLOB, img_major_mime CLOB DEFAULT 'unknown', img_minor_mime CLOB DEFAULT 'unknown', - img_description CLOB NOT NULL, + img_description CLOB, img_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, img_user_text CLOB NOT NULL, img_timestamp TIMESTAMP WITH TIME ZONE @@ -236,7 +236,7 @@ CREATE INDEX img_timestamp_idx ON image (img_timestamp); CREATE TABLE oldimage ( oi_name VARCHAR(255) NOT NULL REFERENCES image(img_name), - oi_archive_name VARCHAR(255) NOT NULL, + oi_archive_name VARCHAR(255), oi_size INTEGER NOT NULL, oi_width INTEGER NOT NULL, oi_height INTEGER NOT NULL, @@ -244,9 +244,15 @@ CREATE TABLE oldimage ( oi_description CLOB, oi_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, oi_user_text CLOB NOT NULL, - oi_timestamp TIMESTAMP WITH TIME ZONE NOT NULL -); -CREATE INDEX oi_name ON oldimage (oi_name); + oi_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, + oi_metadata CLOB, + oi_media_type VARCHAR(10) DEFAULT NULL, + oi_major_mime VARCHAR(11) DEFAULT 'unknown', + oi_minor_mime VARCHAR(32) DEFAULT 'unknown', + oi_deleted INTEGER DEFAULT 0 NOT NULL +); +CREATE INDEX oi_name_timestamp ON oldimage (oi_name,oi_timestamp); +CREATE INDEX oi_name_archive_name ON oldimage (oi_name,oi_archive_name); CREATE SEQUENCE filearchive_fa_id_seq; CREATE TABLE filearchive ( diff --git a/maintenance/orphans.php b/maintenance/orphans.php index 0729a239..954117ce 100644 --- a/maintenance/orphans.php +++ b/maintenance/orphans.php @@ -203,4 +203,3 @@ function checkSeparation( $fix ) { } } -?>
\ No newline at end of file diff --git a/maintenance/ourusers.php b/maintenance/ourusers.php index cd5f8ff3..8f1e7c06 100644 --- a/maintenance/ourusers.php +++ b/maintenance/ourusers.php @@ -66,4 +66,4 @@ foreach( $hosts as $host ) { } print "\n"; } -?> + diff --git a/maintenance/parserTests.inc b/maintenance/parserTests.inc index ddf8b89a..510a2db2 100644 --- a/maintenance/parserTests.inc +++ b/maintenance/parserTests.inc @@ -327,6 +327,22 @@ class ParserTest { } } + + /** + * Use a regex to find out the value of an option + * @param $regex A regex, the first group will be the value returned + * @param $opts Options line to look in + * @param $defaults Default value returned if the regex does not match + */ + private static function getOptionValue( $regex, $opts, $default ) { + $m = array(); + if( preg_match( $regex, $opts, $m ) ) { + return $m[1]; + } else { + return $default; + } + } + /** * Set up the global variables for a consistent environment for each test. * Ideally this should replace the global configuration entirely. @@ -342,19 +358,13 @@ class ParserTest { $this->uploadDir = $this->setupUploadDir(); } - $m = array(); - if( preg_match( '/language=([a-z]+(?:_[a-z]+)?)/', $opts, $m ) ) { - $lang = $m[1]; - } else { - $lang = 'en'; - } - - if( preg_match( '/variant=([a-z]+(?:-[a-z]+)?)/', $opts, $m ) ) { - $variant = $m[1]; - } else { - $variant = false; - } - + # Find out values for some special options. + $lang = + self::getOptionValue( '/language=([a-z]+(?:_[a-z]+)?)/', $opts, 'en' ); + $variant = + self::getOptionValue( '/variant=([a-z]+(?:-[a-z]+)?)/', $opts, false ); + $maxtoclevel = + self::getOptionValue( '/wgMaxTocLevel=(\d+)/', $opts, 999 ); $settings = array( 'wgServer' => 'http://localhost', @@ -362,8 +372,15 @@ class ParserTest { 'wgScriptPath' => '/', 'wgArticlePath' => '/wiki/$1', 'wgActionPaths' => array(), - 'wgUploadPath' => 'http://example.com/images', - 'wgUploadDirectory' => $this->uploadDir, + 'wgLocalFileRepo' => array( + 'class' => 'LocalRepo', + 'name' => 'local', + 'directory' => $this->uploadDir, + 'url' => 'http://example.com/images', + 'hashLevels' => 2, + 'transformVia404' => false, + ), + 'wgEnableUploads' => true, 'wgStyleSheetPath' => '/skins', 'wgSitename' => 'MediaWiki', 'wgServerName' => 'Britney Spears', @@ -374,7 +391,7 @@ class ParserTest { 'wgLang' => null, 'wgContLang' => null, 'wgNamespacesWithSubpages' => array( 0 => preg_match('/\\bsubpage\\b/i', $opts)), - 'wgMaxTocLevel' => 999, + 'wgMaxTocLevel' => $maxtoclevel, 'wgCapitalLinks' => true, 'wgNoFollowLinks' => true, 'wgThumbnailScriptPath' => false, @@ -416,7 +433,7 @@ class ParserTest { 'watchlist', 'math', 'searchindex', 'interwiki', 'querycache', 'objectcache', 'job', 'redirect', - 'querycachetwo' + 'querycachetwo', 'archive', 'user_groups' ); // Allow extensions to add to the list of tables to duplicate; @@ -531,20 +548,12 @@ class ParserTest { */ private function setupUploadDir() { global $IP; - $dir = wfTempDir() . "/mwParser-" . mt_rand() . "-images"; + wfDebug( "Creating upload directory $dir\n" ); mkdir( $dir ); mkdir( $dir . '/3' ); mkdir( $dir . '/3/3a' ); - - $img = "$IP/skins/monobook/headbg.jpg"; - $h = fopen($img, 'r'); - $c = fread($h, filesize($img)); - fclose($h); - - $f = fopen( $dir . '/3/3a/Foobar.jpg', 'wb' ); - fwrite( $f, $c ); - fclose( $f ); + copy( "$IP/skins/monobook/headbg.jpg", "$dir/3/3a/Foobar.jpg" ); return $dir; } @@ -553,6 +562,7 @@ class ParserTest { * after each test runs. */ private function teardownGlobals() { + RepoGroup::destroySingleton(); foreach( $this->savedGlobals as $var => $val ) { $GLOBALS[$var] = $val; } @@ -593,7 +603,7 @@ class ParserTest { } /** - * @desc delete the specified files, if they exist. + * Delete the specified files, if they exist. * @param array $files full paths to files to delete. */ private static function deleteFiles( $files ) { @@ -605,7 +615,7 @@ class ParserTest { } /** - * @desc delete the specified directories, if they exist. Must be empty. + * Delete the specified directories, if they exist. Must be empty. * @param array $dirs full paths to directories to delete. */ private static function deleteDirs( $dirs ) { diff --git a/maintenance/parserTests.php b/maintenance/parserTests.php index 540d6b08..4f8edc12 100644 --- a/maintenance/parserTests.php +++ b/maintenance/parserTests.php @@ -68,4 +68,4 @@ echo( "This is MediaWiki version {$version}.\n\n" ); $ok = $tester->runTestsFromFiles( $files ); exit ($ok ? 0 : -1); -?> + diff --git a/maintenance/parserTests.txt b/maintenance/parserTests.txt index 72e01362..27cc792c 100644 --- a/maintenance/parserTests.txt +++ b/maintenance/parserTests.txt @@ -1227,7 +1227,7 @@ Invalid attributes in table cell (bug 1830) # FIXME: this one has incorrect tag nesting still. !! test -Table security: embedded pipes (http://mail.wikipedia.org/pipermail/wikitech-l/2006-April/034637.html) +Table security: embedded pipes (http://lists.wikimedia.org/mailman/htdig/wikitech-l/2006-April/022293.html) !! input {| | |[ftp://|x||]" onmouseover="alert(document.cookie)">test @@ -1903,7 +1903,7 @@ Magic Word: {{NUMBEROFARTICLES}} !! input {{NUMBEROFARTICLES}} !! result -<p>1 +<p>2 </p> !! end @@ -2267,7 +2267,7 @@ Template with thumb image (with link in description) {{paramtest| param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}} !! result -This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:122px;"><a href="/index.php?title=Special:Upload&wpDestFile=Noimage.png" class="new" title="Image:Noimage.png">Image:Noimage.png</a> <div class="thumbcaption"><a href="/index.php?title=No_link&action=edit" class="new" title="No link">link</a> <a href="/index.php?title=No_link&action=edit" class="new" title="No link">caption</a></div></div></div> +This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&wpDestFile=Noimage.png" class="new" title="Image:Noimage.png">Image:Noimage.png</a> <div class="thumbcaption"><a href="/index.php?title=No_link&action=edit" class="new" title="No link">link</a> <a href="/index.php?title=No_link&action=edit" class="new" title="No link">caption</a></div></div></div> !! end @@ -2946,7 +2946,7 @@ Simple image !! input [[Image:foobar.jpg]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img alt="Image:foobar.jpg" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img alt="Image:foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -2955,7 +2955,7 @@ Right-aligned image !! input [[Image:foobar.jpg|right]] !! result -<div class="floatright"><span><a href="/wiki/Image:Foobar.jpg" class="image" title=""><img alt="" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></span></div> +<div class="floatright"><span><a href="/wiki/Image:Foobar.jpg" class="image" title="Foobar.jpg"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a></span></div> !! end @@ -2964,7 +2964,7 @@ Image with caption !! input [[Image:foobar.jpg|right|Caption text]] !! result -<div class="floatright"><span><a href="/wiki/Image:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></span></div> +<div class="floatright"><span><a href="/wiki/Image:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a></span></div> !! end @@ -2973,7 +2973,7 @@ Image with frame and link !! input [[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]]] !! result -<div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a test image Main Page"><img alt="This is a test image Main Page" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div> +<div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="This is a test image Main Page"><img alt="This is a test image Main Page" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" class="thumbimage" /></a> <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div> !! end @@ -2993,7 +2993,7 @@ Frameless image caption with a free URL !! input [[Image:foobar.jpg|http://example.com]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="http://example.com"><img alt="http://example.com" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="http://example.com"><img alt="http://example.com" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -3002,7 +3002,7 @@ Thumbnail image caption with a free URL !! input [[Image:foobar.jpg|thumb|http://example.com]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="http://example.com"><img alt="http://example.com" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a></div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="http://example.com"><img alt="http://example.com" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a></div></div></div> !! end @@ -3011,7 +3011,7 @@ BUG 1887: A ISBN with a thumbnail !! input [[Image:foobar.jpg|thumb|ISBN 1235467890]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="ISBN 1235467890"><img alt="ISBN 1235467890" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="/index.php?title=Special:Booksources&isbn=1235467890" class="internal">ISBN 1235467890</a></div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="ISBN 1235467890"><img alt="ISBN 1235467890" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="/index.php?title=Special:Booksources&isbn=1235467890" class="internal">ISBN 1235467890</a></div></div></div> !! end @@ -3020,7 +3020,7 @@ BUG 1887: A RFC with a thumbnail !! input [[Image:foobar.jpg|thumb|This is RFC 12354]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is RFC 12354"><img alt="This is RFC 12354" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a href="http://tools.ietf.org/html/rfc12354" class="external" title="http://tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="This is RFC 12354"><img alt="This is RFC 12354" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a href="http://tools.ietf.org/html/rfc12354" class="external" title="http://tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div> !! end @@ -3029,7 +3029,7 @@ BUG 1887: A mailto link with a thumbnail !! input [[Image:foobar.jpg|thumb|Please mailto:nobody@example.com]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Please mailto:nobody@example.com"><img alt="Please mailto:nobody@example.com" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Please <a href="mailto:nobody@example.com" class="external free" title="mailto:nobody@example.com" rel="nofollow">mailto:nobody@example.com</a></div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="Please mailto:nobody@example.com"><img alt="Please mailto:nobody@example.com" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Please <a href="mailto:nobody@example.com" class="external free" title="mailto:nobody@example.com" rel="nofollow">mailto:nobody@example.com</a></div></div></div> !! end @@ -3039,7 +3039,7 @@ so math is not stripped and turns up as escaped <math> tags. !! input [[Image:foobar.jpg|thumb|<math>2+2</math>]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="<math>2+2</math>"><img alt="<math>2+2</math>" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><math>2+2</math></div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="<math>2+2</math>"><img alt="<math>2+2</math>" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><math>2+2</math></div></div></div> !! end @@ -3050,7 +3050,7 @@ math !! input [[Image:foobar.jpg|thumb|<math>2+2</math>]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="2 + 2"><img alt="2 + 2" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><span class="texhtml">2 + 2</span></div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="2 + 2"><img alt="2 + 2" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><span class="texhtml">2 + 2</span></div></div></div> !! end @@ -3060,7 +3060,7 @@ BUG 648: Frameless image caption with a link !! input [[Image:foobar.jpg|text with a [[link]] in it]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -3069,7 +3069,7 @@ BUG 648: Frameless image caption with a link (suffix) !! input [[Image:foobar.jpg|text with a [[link]]foo in it]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a linkfoo in it"><img alt="text with a linkfoo in it" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a linkfoo in it"><img alt="text with a linkfoo in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -3078,7 +3078,7 @@ BUG 648: Frameless image caption with an interwiki link !! input [[Image:foobar.jpg|text with a [[MeatBall:Link]] in it]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a MeatBall:Link in it"><img alt="text with a MeatBall:Link in it" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a MeatBall:Link in it"><img alt="text with a MeatBall:Link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -3087,7 +3087,7 @@ BUG 648: Frameless image caption with a piped interwiki link !! input [[Image:foobar.jpg|text with a [[MeatBall:Link|link]] in it]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -3096,7 +3096,7 @@ Escape HTML special chars in image alt text !! input [[Image:foobar.jpg|& < > "]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="& < > ""><img alt="& < > "" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="& < > ""><img alt="& < > "" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -3105,7 +3105,7 @@ BUG 499: Alt text should have Ӓ, not &1234; !! input [[Image:foobar.jpg|♀]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="♀"><img alt="♀" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="♀"><img alt="♀" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !! end @@ -3123,7 +3123,7 @@ Image caption containing another image !! input [[Image:Foobar.jpg|thumb|This is a caption with another [[Image:icon.png|image]] inside it!]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a caption with another Image:Icon.png inside it!"><img alt="This is a caption with another Image:Icon.png inside it!" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&wpDestFile=Icon.png" class="new" title="Image:Icon.png">Image:Icon.png</a> inside it!</div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="This is a caption with another Image:Icon.png inside it!"><img alt="This is a caption with another Image:Icon.png inside it!" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&wpDestFile=Icon.png" class="new" title="Image:Icon.png">Image:Icon.png</a> inside it!</div></div></div> !! end @@ -3133,7 +3133,7 @@ Image caption containing a newline [[Image:Foobar.jpg|This *is some text]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title="This *is some text"><img alt="This *is some text" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="This *is some text"><img alt="This *is some text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !!end @@ -3143,7 +3143,7 @@ Bug 3090: External links other than http: in image captions !! input [[Image:Foobar.jpg|thumb|200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This caption has irc and Secure ext links in it."><img alt="This caption has irc and Secure ext links in it." longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This caption has <a href="irc://example.net" class="external text" title="irc://example.net" rel="nofollow">irc</a> and <a href="https://example.com" class="external text" title="https://example.com" rel="nofollow">Secure</a> ext links in it.</div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="This caption has irc and Secure ext links in it."><img alt="This caption has irc and Secure ext links in it." src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This caption has <a href="irc://example.net" class="external text" title="irc://example.net" rel="nofollow">irc</a> and <a href="https://example.com" class="external text" title="https://example.com" rel="nofollow">Secure</a> ext links in it.</div></div></div> !! end @@ -3408,6 +3408,42 @@ TOC regression (bug 9764) !! end !! test +TOC with wgMaxTocLevel=3 (bug 6204) +!! options +wgMaxTocLevel=3 +!! input +== title 1 == +=== title 1.1 === +==== title 1.1.1 ==== +=== title 1.2 === +== title 2 == +=== title 2.1 === +!! result +<table id="toc" class="toc" summary="Contents"><tr><td><div id="toctitle"><h2>Contents</h2></div> +<ul> +<li class="toclevel-1"><a href="#title_1"><span class="tocnumber">1</span> <span class="toctext">title 1</span></a> +<ul> +<li class="toclevel-2"><a href="#title_1.1"><span class="tocnumber">1.1</span> <span class="toctext">title 1.1</span></a></li> +<li class="toclevel-2"><a href="#title_1.2"><span class="tocnumber">1.2</span> <span class="toctext">title 1.2</span></a></li> +</ul> +</li> +<li class="toclevel-1"><a href="#title_2"><span class="tocnumber">2</span> <span class="toctext">title 2</span></a> +<ul> +<li class="toclevel-2"><a href="#title_2.1"><span class="tocnumber">2.1</span> <span class="toctext">title 2.1</span></a></li> +</ul> +</li> +</ul> +</td></tr></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script> +<a name="title_1"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: title 1">edit</a>]</span> <span class="mw-headline"> title 1 </span></h2> +<a name="title_1.1"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&action=edit&section=2" title="Edit section: title 1.1">edit</a>]</span> <span class="mw-headline"> title 1.1 </span></h3> +<a name="title_1.1.1"></a><h4><span class="editsection">[<a href="/index.php?title=Parser_test&action=edit&section=3" title="Edit section: title 1.1.1">edit</a>]</span> <span class="mw-headline"> title 1.1.1 </span></h4> +<a name="title_1.2"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&action=edit&section=4" title="Edit section: title 1.2">edit</a>]</span> <span class="mw-headline"> title 1.2 </span></h3> +<a name="title_2"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&action=edit&section=5" title="Edit section: title 2">edit</a>]</span> <span class="mw-headline"> title 2 </span></h2> +<a name="title_2.1"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&action=edit&section=6" title="Edit section: title 2.1">edit</a>]</span> <span class="mw-headline"> title 2.1 </span></h3> + +!! end + +!! test Resolving duplicate section names !! input == Foo bar == @@ -3467,7 +3503,7 @@ BUG 1219 URL next to image (good) !! input http://example.com [[Image:foobar.jpg]] !! result -<p><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a> <a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img alt="Image:foobar.jpg" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a> <a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img alt="Image:foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !!end @@ -3476,7 +3512,7 @@ BUG 1219 URL next to image (broken) !! input http://example.com[[Image:foobar.jpg]] !! result -<p><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a><a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img alt="Image:foobar.jpg" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a> +<p><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a><a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img alt="Image:foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a> </p> !!end @@ -4751,7 +4787,7 @@ Fuzz testing: image with bogus manual thumbnail !!input [[Image:foobar.jpg|thumbnail= ]] !!result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title=""><img alt="" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/3/3a/Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:1943px;">Error creating thumbnail: <div class="thumbcaption"></div></div></div> !!end @@ -5796,6 +5832,47 @@ section=1 a !! end + +!! test +Section extraction, <pre> around bogus header (bug 10309) +!! options +noxml section=2 +!! input +== Section One == +<pre> +======= +</pre> + +== Section Two == +stuff +!! result +== Section Two == +stuff +!! end + +!! test +Section replacement, <pre> around bogus header (bug 10309) +!! options +noxml replace=2,"xxx" +!! input +== Section One == +<pre> +======= +</pre> + +== Section Two == +stuff +!! result +== Section One == +<pre> +======= +</pre> + +xxx +!! end + + + !! test Handling of 
 in URLs !! input @@ -6003,7 +6080,7 @@ Centre-aligned image !! input [[Image:foobar.jpg|centre]] !! result -<div class="center"><div class="floatnone"><span><a href="/wiki/Image:Foobar.jpg" class="image" title=""><img alt="" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></span></div></div> +<div class="center"><div class="floatnone"><span><a href="/wiki/Image:Foobar.jpg" class="image" title="Foobar.jpg"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a></span></div></div> !!end @@ -6012,7 +6089,7 @@ None-aligned image !! input [[Image:foobar.jpg|none]] !! result -<div class="floatnone"><span><a href="/wiki/Image:Foobar.jpg" class="image" title=""><img alt="" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></span></div> +<div class="floatnone"><span><a href="/wiki/Image:Foobar.jpg" class="image" title="Foobar.jpg"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" border="0" /></a></span></div> !!end @@ -6021,7 +6098,7 @@ Width + Height sized image (using px) (height is ignored) !! input [[Image:foobar.jpg|640x480px]] !! result -<p><a href="/wiki/Image:Foobar.jpg" class="image" title=""><img alt="" longdesc="/wiki/Image:Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" /></a> +<p><a href="/wiki/Image:Foobar.jpg" class="image" title="Foobar.jpg"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" border="0" /></a> </p> !!end @@ -6059,7 +6136,7 @@ Images with the "|" character in the comment !! input [[image:Foobar.jpg|thumb|An [http://test/?param1=|left|¶m2=|x external] URL]] !! result -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="An external URL"><img alt="An external URL" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>An <a href="http://test/?param1=|left|&param2=|x" class="external text" title="http://test/?param1=|left|&param2=|x" rel="nofollow">external</a> URL</div></div></div> +<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="image" title="An external URL"><img alt="An external URL" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" border="0" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>An <a href="http://test/?param1=|left|&param2=|x" class="external text" title="http://test/?param1=|left|&param2=|x" rel="nofollow">external</a> URL</div></div></div> !!end diff --git a/maintenance/parserTestsParserHook.php b/maintenance/parserTestsParserHook.php index 339cadab..0005e999 100644 --- a/maintenance/parserTestsParserHook.php +++ b/maintenance/parserTestsParserHook.php @@ -30,4 +30,4 @@ function wfParserTestParserHookHook( $in, $argv ) { return "<pre>\n$ret</pre>"; } -?> + diff --git a/maintenance/parserTestsParserTime.php b/maintenance/parserTestsParserTime.php index 68541cfb..70a04d91 100644 --- a/maintenance/parserTestsParserTime.php +++ b/maintenance/parserTestsParserTime.php @@ -22,4 +22,4 @@ function wfParserTimeSetup( &$parser, &$ts ) { return true; } -?> + diff --git a/maintenance/parserTestsStaticParserHook.php b/maintenance/parserTestsStaticParserHook.php index 8f22101f..f72fcda9 100644 --- a/maintenance/parserTestsStaticParserHook.php +++ b/maintenance/parserTestsStaticParserHook.php @@ -40,4 +40,4 @@ function wfParserTestStaticParserHookHook( $in, $argv ) { "argv: " . var_export( $argv, true ) . "\n" ); } -?> + diff --git a/maintenance/postgres/compare_schemas.pl b/maintenance/postgres/compare_schemas.pl index ce045fef..297e3af2 100644 --- a/maintenance/postgres/compare_schemas.pl +++ b/maintenance/postgres/compare_schemas.pl @@ -35,7 +35,7 @@ while (<DATA>) { my $datatype = join '|' => qw( bool tinyint int bigint real float -tinytext mediumtext text char varchar varbinary +tinytext mediumtext text char varchar varbinary binary timestamp datetime tinyblob mediumblob blob ); @@ -155,7 +155,7 @@ CIDR ); $dtype = qr{($dtype)}; my %new; -my ($infunction,$inview,$inrule) = (0,0,0); +my ($infunction,$inview,$inrule,$lastcomma) = (0,0,0,0); seek $newfh, 0, 0; while (<$newfh>) { next if /^\s*\-\-/ or /^\s*$/; @@ -190,11 +190,19 @@ while (<$newfh>) { if (/^CREATE TABLE "?(\w+)"? \($/) { $table = $1; $new{$table}{name}=$table; + $lastcomma = 1; } elsif (/^\);$/) { + if ($lastcomma) { + warn "Stray comma before line $.\n"; + } } - elsif (/^ (\w+) +$dtype/) { + elsif (/^ (\w+) +$dtype.*?(,?)(?: --.*)?$/) { $new{$table}{column}{$1} = $2; + if (!$lastcomma) { + print "Missing comma before line $. of $new\n"; + } + $lastcomma = $3 ? 1 : 0; } else { die "Cannot parse line $. of $new:\n$_\n"; diff --git a/maintenance/postgres/tables.sql b/maintenance/postgres/tables.sql index e5dd129b..8f99c84a 100644 --- a/maintenance/postgres/tables.sql +++ b/maintenance/postgres/tables.sql @@ -128,6 +128,7 @@ CREATE TABLE archive ( ar_namespace SMALLINT NOT NULL, ar_title TEXT NOT NULL, ar_text TEXT, + ar_page_id INTEGER NULL, ar_comment TEXT, ar_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, ar_user_text TEXT NOT NULL, @@ -140,6 +141,7 @@ CREATE TABLE archive ( ar_len INTEGER NULL ); CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp); +CREATE INDEX archive_user_text ON archive (ar_user_text); CREATE TABLE redirect ( @@ -177,7 +179,7 @@ CREATE TABLE categorylinks ( cl_timestamp TIMESTAMPTZ NOT NULL ); CREATE UNIQUE INDEX cl_from ON categorylinks (cl_from, cl_to); -CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_sortkey); +CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_sortkey, cl_from); CREATE TABLE externallinks ( el_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, @@ -227,7 +229,9 @@ CREATE TABLE ipblocks ( ipb_expiry TIMESTAMPTZ NOT NULL, ipb_range_start TEXT, ipb_range_end TEXT, - ipb_deleted INTEGER NOT NULL DEFAULT 0 + ipb_deleted INTEGER NOT NULL DEFAULT 0, + ipb_block_email CHAR NOT NULL DEFAULT '0' + ); CREATE INDEX ipb_address ON ipblocks (ipb_address); CREATE INDEX ipb_user ON ipblocks (ipb_user); @@ -247,10 +251,12 @@ CREATE TABLE image ( img_description TEXT NOT NULL, img_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, img_user_text TEXT NOT NULL, - img_timestamp TIMESTAMPTZ + img_timestamp TIMESTAMPTZ, + img_sha1 TEXT NOT NULL DEFAULT '' ); CREATE INDEX img_size_idx ON image (img_size); CREATE INDEX img_timestamp_idx ON image (img_timestamp); +CREATE INDEX img_sha1 ON image (img_sha1); CREATE TABLE oldimage ( oi_name TEXT NOT NULL REFERENCES image(img_name), @@ -262,9 +268,17 @@ CREATE TABLE oldimage ( oi_description TEXT, oi_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, oi_user_text TEXT NOT NULL, - oi_timestamp TIMESTAMPTZ NOT NULL + oi_timestamp TIMESTAMPTZ NOT NULL, + oi_metadata BYTEA NOT NULL DEFAULT '', + oi_media_type TEXT NULL, + oi_major_mime TEXT NOT NULL DEFAULT 'unknown', + oi_minor_mime TEXT NOT NULL DEFAULT 'unknown', + oi_deleted CHAR NOT NULL DEFAULT '0', + oi_sha1 TEXT NOT NULL DEFAULT '' ); -CREATE INDEX oi_name ON oldimage (oi_name); +CREATE INDEX oi_name_timestamp ON oldimage (oi_name,oi_timestamp); +CREATE INDEX oi_name_archive_name ON oldimage (oi_name,oi_archive_name); +CREATE INDEX oi_sha1 ON oldimage (oi_sha1); CREATE TABLE filearchive ( @@ -511,6 +525,6 @@ CREATE TABLE mediawiki_version ( ); INSERT INTO mediawiki_version (type,mw_version,sql_version,sql_date) - VALUES ('Creation','??','$LastChangedRevision: 20687 $','$LastChangedDate: 2007-03-25 20:12:26 -0400 (Sun, 25 Mar 2007) $'); + VALUES ('Creation','??','$LastChangedRevision: 25527 $','$LastChangedDate: 2007-09-05 04:14:18 -0400 (Wed, 05 Sep 2007) $'); diff --git a/maintenance/purgeList.php b/maintenance/purgeList.php index abe76683..99fb8a87 100644 --- a/maintenance/purgeList.php +++ b/maintenance/purgeList.php @@ -34,4 +34,4 @@ $u->doUpdate(); echo "Done!\n"; -?> + diff --git a/maintenance/purgeOldText.php b/maintenance/purgeOldText.php index 2147ee37..3e80c320 100644 --- a/maintenance/purgeOldText.php +++ b/maintenance/purgeOldText.php @@ -26,4 +26,3 @@ function ShowUsage() { echo( " help : Show this usage information\n" ); } -?>
\ No newline at end of file diff --git a/maintenance/reassignEdits.inc.php b/maintenance/reassignEdits.inc.php index 9f5c9c02..da050163 100644 --- a/maintenance/reassignEdits.inc.php +++ b/maintenance/reassignEdits.inc.php @@ -140,4 +140,3 @@ function initialiseUser( $username ) { return $user; } -?>
\ No newline at end of file diff --git a/maintenance/reassignEdits.php b/maintenance/reassignEdits.php index 691fefc1..07f81b8a 100644 --- a/maintenance/reassignEdits.php +++ b/maintenance/reassignEdits.php @@ -53,4 +53,3 @@ function ShowUsage() { echo( " --report : Print out details of what would be changed, but don't update it\n\n" ); } -?>
\ No newline at end of file diff --git a/maintenance/rebuildImages.php b/maintenance/rebuildImages.php index 4c02dc9c..dfdb3b20 100644 --- a/maintenance/rebuildImages.php +++ b/maintenance/rebuildImages.php @@ -40,6 +40,16 @@ class ImageBuilder extends FiveUpgrade { $this->maxLag = 10; # if slaves are lagged more than 10 secs, wait $this->dryrun = $dryrun; + if ( $dryrun ) { + $GLOBALS['wgReadOnly'] = 'Dry run mode, image upgrades are suppressed'; + } + } + + function getRepo() { + if ( !isset( $this->repo ) ) { + $this->repo = RepoGroup::singleton()->getLocalRepo(); + } + return $this->repo; } function build() { @@ -94,13 +104,7 @@ class ImageBuilder extends FiveUpgrade { while( $row = $this->dbr->fetchObject( $result ) ) { $update = call_user_func( $callback, $row ); - if( is_array( $update ) ) { - if( !$this->dryrun ) { - $this->dbw->update( $table, - $update, - array( $key => $row->$key ), - $fname ); - } + if( $update ) { $this->progress( 1 ); } else { $this->progress( 0 ); @@ -116,97 +120,43 @@ class ImageBuilder extends FiveUpgrade { } function imageCallback( $row ) { - if( $row->img_width ) { - // Already processed - return null; - } - - // Fill in the new image info fields - $info = $this->imageInfo( $row->img_name ); - - global $wgMemc; - $key = wfMemcKey( "Image", md5( $row->img_name ) ); - $wgMemc->delete( $key ); - - return array( - 'img_width' => $info['width'], - 'img_height' => $info['height'], - 'img_bits' => $info['bits'], - 'img_media_type' => $info['media'], - 'img_major_mime' => $info['major'], - 'img_minor_mime' => $info['minor'] ); + // Create a File object from the row + // This will also upgrade it + $file = $this->getRepo()->newFileFromRow( $row ); + return $file->getUpgraded(); } - function buildOldImage() { $this->buildTable( 'oldimage', 'oi_archive_name', array( &$this, 'oldimageCallback' ) ); } function oldimageCallback( $row ) { - if( $row->oi_width ) { - return null; + // Create a File object from the row + // This will also upgrade it + if ( $row->oi_archive_name == '' ) { + $this->log( "Empty oi_archive_name for oi_name={$row->oi_name}" ); + return false; } - - // Fill in the new image info fields - $info = $this->imageInfo( $row->oi_archive_name, 'wfImageArchiveDir', $row->oi_name ); - return array( - 'oi_width' => $info['width' ], - 'oi_height' => $info['height'], - 'oi_bits' => $info['bits' ] ); + $file = $this->getRepo()->newFileFromRow( $row ); + return $file->getUpgraded(); } function crawlMissing() { - global $wgUploadDirectory, $wgHashedUploadDirectory; - if( $wgHashedUploadDirectory ) { - for( $i = 0; $i < 16; $i++ ) { - for( $j = 0; $j < 16; $j++ ) { - $dir = sprintf( '%s%s%01x%s%02x', - $wgUploadDirectory, - DIRECTORY_SEPARATOR, - $i, - DIRECTORY_SEPARATOR, - $i * 16 + $j ); - $this->crawlDirectory( $dir ); - } - } - } else { - $this->crawlDirectory( $wgUploadDirectory ); - } + $repo = RepoGroup::singleton()->getLocalRepo(); + $repo->enumFilesInFS( array( $this, 'checkMissingImage' ) ); } - function crawlDirectory( $dir ) { - if( !file_exists( $dir ) ) { - return $this->log( "no directory, skipping $dir" ); - } - if( !is_dir( $dir ) ) { - return $this->log( "not a directory?! skipping $dir" ); - } - if( !is_readable( $dir ) ) { - return $this->log( "dir not readable, skipping $dir" ); - } - $source = opendir( $dir ); - if( $source === false ) { - return $this->log( "couldn't open dir, skipping $dir" ); + function checkMissingImage( $fullpath ) { + $fname = 'ImageBuilder::checkMissingImage'; + $filename = wfBaseName( $fullpath ); + if( is_dir( $fullpath ) ) { + return; } - - $this->log( "crawling $dir" ); - while( false !== ( $filename = readdir( $source ) ) ) { - $fullpath = $dir . DIRECTORY_SEPARATOR . $filename; - if( is_dir( $fullpath ) ) { - continue; - } - if( is_link( $fullpath ) ) { - $this->log( "skipping symlink at $fullpath" ); - continue; - } - $this->checkMissingImage( $filename, $fullpath ); + if( is_link( $fullpath ) ) { + $this->log( "skipping symlink at $fullpath" ); + return; } - closedir( $source ); - } - - function checkMissingImage( $filename, $fullpath ) { - $fname = 'ImageBuilder::checkMissingImage'; $row = $this->dbw->selectRow( 'image', array( 'img_name' ), array( 'img_name' => $filename ), @@ -223,8 +173,6 @@ class ImageBuilder extends FiveUpgrade { function addMissingImage( $filename, $fullpath ) { $fname = 'ImageBuilder::addMissingImage'; - $size = filesize( $fullpath ); - $info = $this->imageInfo( $filename ); $timestamp = $this->dbw->timestamp( filemtime( $fullpath ) ); global $wgContLang; @@ -242,23 +190,14 @@ class ImageBuilder extends FiveUpgrade { $this->log( "Empty filename for $fullpath" ); return; } - - $fields = array( - 'img_name' => $filename, - 'img_size' => $size, - 'img_width' => $info['width'], - 'img_height' => $info['height'], - 'img_metadata' => '', // filled in on-demand - 'img_bits' => $info['bits'], - 'img_media_type' => $info['media'], - 'img_major_mime' => $info['major'], - 'img_minor_mime' => $info['minor'], - 'img_description' => '(recovered file, missing upload log entry)', - 'img_user' => 0, - 'img_user_text' => 'Conversion script', - 'img_timestamp' => $timestamp ); - if( !$this->dryrun ) { - $this->dbw->insert( 'image', $fields, $fname ); + if ( !$this->dryrun ) { + $file = wfLocalFile( $filename ); + if ( !$file->recordUpload( '', '(recovered file, missing upload log entry)', '', '', '', + false, $timestamp ) ) + { + $this->log( "Error uploading file $fullpath" ); + return; + } } $this->log( $fullpath ); } @@ -271,4 +210,4 @@ if( isset( $options['missing'] ) ) { $builder->build(); } -?> + diff --git a/maintenance/rebuildInterwiki.php b/maintenance/rebuildInterwiki.php index b3656bb1..bc0a0008 100644 --- a/maintenance/rebuildInterwiki.php +++ b/maintenance/rebuildInterwiki.php @@ -27,4 +27,4 @@ if ( isset( $options['o'] ) ) { print $sql; } -?> + diff --git a/maintenance/rebuildall.php b/maintenance/rebuildall.php index 4ac91eed..002e6fad 100644 --- a/maintenance/rebuildall.php +++ b/maintenance/rebuildall.php @@ -35,4 +35,4 @@ refreshLinks( 1 ); print "Done.\n"; exit(); -?> + diff --git a/maintenance/rebuildrecentchanges.inc b/maintenance/rebuildrecentchanges.inc index 9f1abf1b..51018153 100644 --- a/maintenance/rebuildrecentchanges.inc +++ b/maintenance/rebuildrecentchanges.inc @@ -49,10 +49,9 @@ function rebuildRecentChangesTablePass2() $dbw = wfGetDB( DB_MASTER ); list ($recentchanges, $revision) = $dbw->tableNamesN( 'recentchanges', 'revision' ); - print( "Updating links...\n" ); + print( "Updating links and size differences...\n" ); # Fill in the rc_last_oldid field, which points to the previous edit - # $sql = "SELECT rc_cur_id,rc_this_oldid,rc_timestamp FROM $recentchanges " . "ORDER BY rc_cur_id,rc_timestamp"; $res = $dbw->query( $sql, DB_MASTER ); @@ -65,15 +64,17 @@ function rebuildRecentChangesTablePass2() # Switch! Look up the previous last edit, if any $lastCurId = intval( $obj->rc_cur_id ); $emit = $obj->rc_timestamp; - $sql2 = "SELECT rev_id FROM $revision " . + $sql2 = "SELECT rev_id, rev_len FROM $revision " . "WHERE rev_page={$lastCurId} ". "AND rev_timestamp<'{$emit}' ORDER BY rev_timestamp DESC LIMIT 1"; $res2 = $dbw->query( $sql2 ); if( $row = $dbw->fetchObject( $res2 ) ) { $lastOldId = intval( $row->rev_id ); + $lastSize = $row->rev_len; # Grab the last text size } else { # No previous edit $lastOldId = 0; + $lastSize = 'NULL'; $new = 1; } $dbw->freeResult( $res2 ); @@ -81,13 +82,89 @@ function rebuildRecentChangesTablePass2() if( $lastCurId == 0 ) { print "Uhhh, something wrong? No curid\n"; } else { - $sql3 = "UPDATE $recentchanges SET rc_last_oldid=$lastOldId,rc_new=$new,rc_type=$new " . + # Grab the entry's text size + $size = $dbw->selectField( 'revision', 'rev_len', array('rev_id' => $obj->rc_this_oldid ) ); + $size = $size ? $size : 'NULL'; + + $sql3 = "UPDATE $recentchanges SET rc_last_oldid=$lastOldId,rc_new=$new,rc_type=$new," . + "rc_old_len='$lastSize',rc_new_len='$size' " . "WHERE rc_cur_id={$lastCurId} AND rc_this_oldid={$obj->rc_this_oldid}"; $dbw->query( $sql3 ); + $lastOldId = intval( $obj->rc_this_oldid ); } } $dbw->freeResult( $res ); } +function rebuildRecentChangesTablePass3() +{ + global $wgGroupPermissions, $wgUseRCPatrol; + + $dbw = wfGetDB( DB_MASTER ); + + list ($recentchanges, $usergroups) = $dbw->tableNamesN( 'recentchanges', 'user_groups' ); + + $botgroups = $autopatrolgroups = array(); + foreach( $wgGroupPermissions as $group => $rights ) { + if( isset( $rights['bot'] ) && $rights['bot'] == true ) { + $botgroups[] = "'" . $dbw->strencode( $group ) . "'"; + } + if( $wgUseRCPatrol && isset( $rights['autopatrol'] ) && $rights['autopatrol'] == true ) { + $autopatrolgroups[] = "'" . $dbw->strencode( $group ) . "'"; + } + } + # Flag our recent bot edits + if( !empty($botgroups) ) { + $botwhere = implode(',',$botgroups); + $botusers = array(); + + print( "Flagging bot account edits...\n" ); + + # Find all users in RC that are bots + $sql = "SELECT DISTINCT rc_user FROM $recentchanges " . + "LEFT JOIN $usergroups ON rc_user=ug_user " . + "WHERE ug_group IN($botwhere)"; + $res = $dbw->query( $sql, DB_MASTER ); + + while( $obj = $dbw->fetchObject( $res ) ) { + $botusers[] = $obj->rc_user; + } + # Fill in the rc_bot field + if( !empty($botusers) ) { + $botwhere = implode(',',$botusers); + $sql2 = "UPDATE $recentchanges SET rc_bot=1 " . + "WHERE rc_user IN($botwhere)"; + $dbw->query( $sql2 ); + } + } + # Flag our recent autopatrolled edits + if( !empty($autopatrolgroups) ) { + $patrolwhere = implode(',',$autopatrolgroups); + $patrolusers = array(); + + print( "Flagging auto-patrolled edits...\n" ); + + # Find all users in RC with autopatrol rights + $sql = "SELECT DISTINCT rc_user FROM $recentchanges " . + "LEFT JOIN $usergroups ON rc_user=ug_user " . + "WHERE ug_group IN($patrolwhere)"; + $res = $dbw->query( $sql, DB_MASTER ); + + while( $obj = $dbw->fetchObject( $res ) ) { + $patrolusers[] = $obj->rc_user; + } + + # Fill in the rc_patrolled field + if( !empty($patrolusers) ) { + $patrolwhere = implode(',',$patrolusers); + $sql2 = "UPDATE $recentchanges SET rc_patrolled=1 " . + "WHERE rc_user IN($patrolwhere)"; + $dbw->query( $sql2 ); + } + } + + $dbw->freeResult( $res ); +} + ?> diff --git a/maintenance/rebuildrecentchanges.php b/maintenance/rebuildrecentchanges.php index 7fe91dd3..a94780e2 100644 --- a/maintenance/rebuildrecentchanges.php +++ b/maintenance/rebuildrecentchanges.php @@ -17,8 +17,9 @@ $wgDBpassword = $wgDBadminpassword; rebuildRecentChangesTablePass1(); rebuildRecentChangesTablePass2(); +rebuildRecentChangesTablePass3(); // flag bot edits print "Done.\n"; exit(); -?> + diff --git a/maintenance/rebuildtextindex.php b/maintenance/rebuildtextindex.php index 6f31cbb6..47d297a9 100644 --- a/maintenance/rebuildtextindex.php +++ b/maintenance/rebuildtextindex.php @@ -3,6 +3,9 @@ * Rebuild search index table from scratch. This takes several * hours, depending on the database size and server configuration. * + * This is only for MySQL (see bug 9905). For postgres we can probably + * use SearchPostgres::update($pageid); + * * @todo document * @addtogroup Maintenance */ @@ -10,9 +13,14 @@ /** */ require_once( "commandLine.inc" ); require_once( "rebuildtextindex.inc" ); -$wgTitle = Title::newFromText( "Rebuild text index script" ); -$database = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname ); +$database = wfGetDB( DB_MASTER ); +if( !$database instanceof DatabaseMysql ) { + print "This script is only for MySQL.\n"; + exit(); +} + +$wgTitle = Title::newFromText( "Rebuild text index script" ); dropTextIndex( $database ); rebuildTextIndex( $database ); @@ -21,4 +29,4 @@ createTextIndex( $database ); print "Done.\n"; exit(); -?> + diff --git a/maintenance/refreshImageCount.php b/maintenance/refreshImageCount.php index 91145bad..0f06c985 100644 --- a/maintenance/refreshImageCount.php +++ b/maintenance/refreshImageCount.php @@ -22,4 +22,4 @@ $dbw->update( 'site_stats', array( 'ss_images' => $count ), array( 'ss_row_id' => 1 ) ); -?> + diff --git a/maintenance/refreshLinks.inc b/maintenance/refreshLinks.inc index 7a560e97..9e4eea8d 100644 --- a/maintenance/refreshLinks.inc +++ b/maintenance/refreshLinks.inc @@ -8,7 +8,7 @@ define( "REPORTING_INTERVAL", 100 ); #define( "REPORTING_INTERVAL", 1 ); -function refreshLinks( $start, $newOnly = false, $maxLag = false, $end = 0 ) { +function refreshLinks( $start, $newOnly = false, $maxLag = false, $end = 0, $redirectsOnly = false ) { global $wgUser, $wgParser, $wgUseImageResize, $wgUseTidy; $fname = 'refreshLinks'; @@ -25,8 +25,10 @@ function refreshLinks( $start, $newOnly = false, $maxLag = false, $end = 0 ) { $wgUseImageResize = false; $wgUseTidy = false; + $what = ($redirectsOnly)? "redirects" : "links"; + if ( $newOnly ) { - print "Refreshing links from "; + print "Refreshing $what from "; $res = $dbr->select( 'page', array( 'page_id' ), array( @@ -43,11 +45,13 @@ function refreshLinks( $start, $newOnly = false, $maxLag = false, $end = 0 ) { print "$i\n"; wfWaitForSlaves( $maxLag ); } - - fixLinksFromArticle( $row->page_id ); + if($redirectsOnly) + fixRedirect( $row->page_id ); + else + fixLinksFromArticle( $row->page_id ); } } else { - print "Refreshing link table.\n"; + print "Refreshing $what table.\n"; if ( !$end ) { $end = $dbr->selectField( 'page', 'max(page_id)', false ); } @@ -59,11 +63,33 @@ function refreshLinks( $start, $newOnly = false, $maxLag = false, $end = 0 ) { print "$id\n"; wfWaitForSlaves( $maxLag ); } - fixLinksFromArticle( $id ); + if($redirectsOnly) + fixRedirect( $id ); + else + fixLinksFromArticle( $id ); } } } +function fixRedirect( $id ){ + global $wgTitle, $wgArticle; + + $wgTitle = Title::newFromID( $id ); + $dbw = wfGetDB( DB_MASTER ); + + if ( is_null( $wgTitle ) ) { + return; + } + $wgArticle = new Article($wgTitle); + + $rt = $wgArticle->followRedirect(); + + if($rt == false || !is_object($rt)) + return; + + $wgArticle->updateRedirectOn($dbw,$rt); +} + function fixLinksFromArticle( $id ) { global $wgTitle, $wgParser; diff --git a/maintenance/refreshLinks.php b/maintenance/refreshLinks.php index 40e12115..34ca53c5 100644 --- a/maintenance/refreshLinks.php +++ b/maintenance/refreshLinks.php @@ -18,7 +18,7 @@ if ( !$options['dfn-only'] ) { $start = 1; } - refreshLinks( $start, $options['new-only'], $options['m'], $options['e'] ); + refreshLinks( $start, $options['new-only'], $options['m'], $options['e'], $options['redirects-only'] ); } // this bit's bad for replication: disabling temporarily // --brion 2005-07-16 @@ -28,4 +28,4 @@ if ( $options['globals'] ) { print_r( $GLOBALS ); } -?> + diff --git a/maintenance/removeUnusedAccounts.php b/maintenance/removeUnusedAccounts.php index 42c5f059..26be1309 100644 --- a/maintenance/removeUnusedAccounts.php +++ b/maintenance/removeUnusedAccounts.php @@ -54,4 +54,4 @@ if( $count > 0 && isset( $options['delete'] ) ) { } echo( "\n" ); -?> + diff --git a/maintenance/renamewiki.php b/maintenance/renamewiki.php index ebfbaea9..d9fe6e76 100644 --- a/maintenance/renamewiki.php +++ b/maintenance/renamewiki.php @@ -57,4 +57,3 @@ if ( count( $stores ) ) { echo "done.\n"; -?>
\ No newline at end of file diff --git a/maintenance/renderDump.php b/maintenance/renderDump.php index 5cb79c53..4b6322d5 100644 --- a/maintenance/renderDump.php +++ b/maintenance/renderDump.php @@ -2,7 +2,7 @@ /** * Take page text out of an XML dump file and render basic HTML out to files. * This is *NOT* suitable for publishing or offline use; it's intended for - * running comparitive tests of parsing behavior using real-world data. + * running comparative tests of parsing behavior using real-world data. * * Templates etc are pulled from the local wiki database, not from the dump. * @@ -30,7 +30,6 @@ $optionsWithArgs = array( 'report' ); require_once( 'commandLine.inc' ); -require_once( 'SpecialImport.php' ); class DumpRenderer { function __construct( $dir ) { @@ -99,4 +98,4 @@ if( isset( $options['output-dir'] ) ) { $render = new DumpRenderer( $dir ); $render->run(); -?> + diff --git a/maintenance/runJobs.php b/maintenance/runJobs.php index 91168e59..4539be05 100644 --- a/maintenance/runJobs.php +++ b/maintenance/runJobs.php @@ -12,13 +12,28 @@ if ( isset( $options['maxjobs'] ) ) { $maxJobs = 10000; } +$type = false; +if ( isset( $options['type'] ) ) + $type = $options['type']; + $wgTitle = Title::newFromText( 'RunJobs.php' ); $dbw = wfGetDB( DB_MASTER ); $n = 0; -while ( $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ) ) { +$conds = array(); +if ($type !== false) + $conds = array('job_cmd' => $type); + +while ( $dbw->selectField( 'job', 'count(*)', $conds, 'runJobs.php' ) ) { $offset=0; - while ( false != ($job = Job::pop($offset)) ) { + for (;;) { + $job = ($type == false) ? + Job::pop($offset, $type) + : Job::pop_type($type); + + if ($job == false) + break; + wfWaitForSlaves( 5 ); print $job->id . " " . $job->toString() . "\n"; $offset=$job->id; @@ -30,4 +45,4 @@ while ( $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ) ) { } } } -?> + diff --git a/maintenance/showJobs.php b/maintenance/showJobs.php index 14aff3d5..2ecc8aca 100644 --- a/maintenance/showJobs.php +++ b/maintenance/showJobs.php @@ -16,4 +16,4 @@ $dbw = wfGetDB( DB_MASTER ); $count = $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ); print $count."\n"; -?> + diff --git a/maintenance/showStats.php b/maintenance/showStats.php index abab26cb..97b6a199 100644 --- a/maintenance/showStats.php +++ b/maintenance/showStats.php @@ -9,7 +9,7 @@ * @author Brion Vibber * @author Rob Church <robchur@gmail.com> * - * @licence GNU General Public License 2.0 or later + * @license GNU General Public License 2.0 or later */ require_once( 'commandLine.inc' ); @@ -43,4 +43,4 @@ foreach( $fields as $field => $desc ) { foreach( $fields as $field => $desc ) { printf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ); } -?> + diff --git a/maintenance/sql.php b/maintenance/sql.php index a536705e..5ec1d8d3 100644 --- a/maintenance/sql.php +++ b/maintenance/sql.php @@ -3,6 +3,8 @@ /** * Send SQL queries from the specified file to the database, performing * variable replacement along the way. + * + * @addtogroup Database */ require_once( dirname(__FILE__) . '/' . 'commandLine.inc' ); @@ -64,4 +66,4 @@ function sqlPrintResult( $res ) { } } -?> + diff --git a/maintenance/stats.php b/maintenance/stats.php index 25bb9cc7..dc8d4b05 100644 --- a/maintenance/stats.php +++ b/maintenance/stats.php @@ -46,4 +46,4 @@ printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); printf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ); printf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable/$total*100 ); -?> + diff --git a/maintenance/storage/checkStorage.php b/maintenance/storage/checkStorage.php index 46b938ef..d50ef366 100644 --- a/maintenance/storage/checkStorage.php +++ b/maintenance/storage/checkStorage.php @@ -8,9 +8,6 @@ define( 'CONCAT_HEADER', 'O:27:"concatenatedgziphistoryblob"' ); if ( !defined( 'MEDIAWIKI' ) ) { require_once( dirname(__FILE__) . '/../commandLine.inc' ); - require_once( 'ExternalStore.php' ); - require_once( 'ExternalStoreDB.php' ); - require_once( 'SpecialImport.php' ); $cs = new CheckStorage; $fix = isset( $options['fix'] ); @@ -467,4 +464,4 @@ class CheckStorage $this->errors['fixed'][$id] = true; } } -?> + diff --git a/maintenance/storage/compressOld.php b/maintenance/storage/compressOld.php index 87aebb78..794e89d1 100644 --- a/maintenance/storage/compressOld.php +++ b/maintenance/storage/compressOld.php @@ -78,4 +78,4 @@ if ( $success ) { exit(); -?> + diff --git a/maintenance/storage/dumpRev.php b/maintenance/storage/dumpRev.php index d35af384..4c31b4e1 100644 --- a/maintenance/storage/dumpRev.php +++ b/maintenance/storage/dumpRev.php @@ -12,4 +12,3 @@ if ( get_class( $obj ) == 'concatenatedgziphistoryblob' ) { var_dump( $obj ); } -?>
\ No newline at end of file diff --git a/maintenance/storage/moveToExternal.php b/maintenance/storage/moveToExternal.php index 6d3ebfcb..993aa64c 100644 --- a/maintenance/storage/moveToExternal.php +++ b/maintenance/storage/moveToExternal.php @@ -110,4 +110,4 @@ function moveToExternal( $cluster, $maxID, $minID = 1 ) { } } -?> + diff --git a/maintenance/storage/resolveStubs.php b/maintenance/storage/resolveStubs.php index 6836ae60..5dfaa598 100644 --- a/maintenance/storage/resolveStubs.php +++ b/maintenance/storage/resolveStubs.php @@ -6,7 +6,6 @@ if ( !defined( 'MEDIAWIKI' ) ) { $optionsWithArgs = array( 'm' ); require_once( dirname(__FILE__) . '/../commandLine.inc' ); - require_once( 'includes/ExternalStoreDB.php' ); resolveStubs(); } @@ -94,4 +93,4 @@ function resolveStub( $id, $stubText, $flags ) { ), $fname ); } -?> + diff --git a/maintenance/tables.sql b/maintenance/tables.sql index f7217692..72a779a9 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -376,8 +376,16 @@ CREATE TABLE /*$wgDBprefix*/archive ( -- Length of this revision in bytes ar_len int unsigned, + + -- Reference to page_id. Useful for sysadmin fixing of large pages + -- merged together in the archives, or for cleanly restoring a page + -- at its original ID number if possible. + -- + -- Will be NULL for pages deleted prior to 1.11. + ar_page_id int unsigned, - KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp) + KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp), + KEY usertext_timestamp (ar_user_text,ar_timestamp) ) /*$wgDBTableOptions*/; @@ -471,7 +479,7 @@ CREATE TABLE /*$wgDBprefix*/categorylinks ( UNIQUE KEY cl_from (cl_from,cl_to), -- We always sort within a given category... - KEY cl_sortkey (cl_to,cl_sortkey), + KEY cl_sortkey (cl_to,cl_sortkey,cl_from), -- Not really used? KEY cl_timestamp (cl_to,cl_timestamp) @@ -621,6 +629,9 @@ CREATE TABLE /*$wgDBprefix*/ipblocks ( -- Flag for entries hidden from users and Sysops ipb_deleted bool NOT NULL default 0, + + -- Block prevents user from accessing Special:Emailuser + ipb_block_email bool NOT NULL default 0, PRIMARY KEY ipb_id (ipb_id), @@ -682,13 +693,20 @@ CREATE TABLE /*$wgDBprefix*/image ( -- Time of the upload. img_timestamp varbinary(14) NOT NULL default '', + -- SHA-1 content hash in base-36 + img_sha1 varbinary(32) NOT NULL default '', + PRIMARY KEY img_name (img_name), + INDEX img_usertext_timestamp (img_user_text,img_timestamp), -- Used by Special:Imagelist for sort-by-size INDEX img_size (img_size), - -- Used by Special:Newimages and Special:Imagelist - INDEX img_timestamp (img_timestamp) + INDEX img_timestamp (img_timestamp), + + -- For future use + INDEX img_sha1 (img_sha1) + ) /*$wgDBTableOptions*/; @@ -715,7 +733,18 @@ CREATE TABLE /*$wgDBprefix*/oldimage ( oi_user_text varchar(255) binary NOT NULL, oi_timestamp binary(14) NOT NULL default '', - INDEX oi_name (oi_name(10)) + oi_metadata mediumblob NOT NULL, + oi_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL, + oi_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown", + oi_minor_mime varbinary(32) NOT NULL default "unknown", + oi_deleted tinyint unsigned NOT NULL default '0', + oi_sha1 varbinary(32) NOT NULL default '', + + INDEX oi_usertext_timestamp (oi_user_text,oi_timestamp), + INDEX oi_name_timestamp (oi_name,oi_timestamp), + -- oi_archive_name truncated to 14 to avoid key length overflow + INDEX oi_name_archive_name (oi_name,oi_archive_name(14)), + INDEX oi_sha1 (oi_sha1) ) /*$wgDBTableOptions*/; @@ -844,7 +873,7 @@ CREATE TABLE /*$wgDBprefix*/recentchanges ( -- Store log action or null rc_log_action varbinary(255) NULL default NULL, -- Log params - rc_params blob NOT NULL default '', + rc_params blob NULL, PRIMARY KEY rc_id (rc_id), INDEX rc_timestamp (rc_timestamp), @@ -961,7 +990,7 @@ CREATE TABLE /*$wgDBprefix*/querycache ( -- Target namespace+title qc_namespace int NOT NULL default '0', - qc_title char(255) binary NOT NULL default '', + qc_title varchar(255) binary NOT NULL default '', KEY (qc_type,qc_value) @@ -1102,11 +1131,11 @@ CREATE TABLE /*$wgDBprefix*/querycachetwo ( -- Target namespace+title qcc_namespace int NOT NULL default '0', - qcc_title char(255) binary NOT NULL default '', + qcc_title varchar(255) binary NOT NULL default '', -- Target namespace+title2 qcc_namespacetwo int NOT NULL default '0', - qcc_titletwo char(255) binary NOT NULL default '', + qcc_titletwo varchar(255) binary NOT NULL default '', KEY qcc_type (qcc_type,qcc_value), KEY qcc_title (qcc_type,qcc_namespace,qcc_title), @@ -1114,7 +1143,7 @@ CREATE TABLE /*$wgDBprefix*/querycachetwo ( ) /*$wgDBTableOptions*/; ---- Used for storing page restrictions (i.e. protection levels) +-- Used for storing page restrictions (i.e. protection levels) CREATE TABLE /*$wgDBprefix*/page_restrictions ( -- Page to apply restrictions to (Foreign Key to page). pr_page int NOT NULL, @@ -1134,7 +1163,6 @@ CREATE TABLE /*$wgDBprefix*/page_restrictions ( PRIMARY KEY pr_pagetype (pr_page,pr_type), UNIQUE KEY pr_id (pr_id), - KEY pr_page (pr_page), KEY pr_typelevel (pr_type,pr_level), KEY pr_level (pr_level), KEY pr_cascade (pr_cascade) diff --git a/maintenance/undelete.php b/maintenance/undelete.php new file mode 100644 index 00000000..c9a2f9ed --- /dev/null +++ b/maintenance/undelete.php @@ -0,0 +1,33 @@ +<?php + +$usage = <<<EOT +Undelete a page +Usage: php undelete.php [-u <user>] [-r <reason>] <pagename> + +EOT; + +$optionsWithArgs = array( 'u', 'r' ); +require_once( 'commandLine.inc' ); + +$user = 'Command line script'; +$reason = ''; + +if ( isset( $options['u'] ) ) { + $user = $options['u']; +} +if ( isset( $options['r'] ) ) { + $reason = $options['r']; +} +$pageName = @$args[0]; +$title = Title::newFromText( $pageName ); +if ( !$title ) { + echo $usage; + exit( 1 ); +} +$wgUser = User::newFromName( $user ); +$archive = new PageArchive( $title ); +echo "Undeleting " . $title->getPrefixedDBkey() . '...'; +$archive->undelete( array(), $reason ); +echo "done\n"; + + diff --git a/maintenance/update.php b/maintenance/update.php index cf380174..2da51b22 100644 --- a/maintenance/update.php +++ b/maintenance/update.php @@ -60,4 +60,4 @@ do_all_updates( $shared, $purge ); print "Done.\n"; -?> + diff --git a/maintenance/updateArticleCount.inc.php b/maintenance/updateArticleCount.inc.php index d4e2a9e8..84fdfddb 100644 --- a/maintenance/updateArticleCount.inc.php +++ b/maintenance/updateArticleCount.inc.php @@ -63,4 +63,4 @@ class ArticleCounter { } -?> + diff --git a/maintenance/updateArticleCount.php b/maintenance/updateArticleCount.php index 03c7939c..eda67d8f 100644 --- a/maintenance/updateArticleCount.php +++ b/maintenance/updateArticleCount.php @@ -38,4 +38,3 @@ if( $result !== false ) { } echo( "\n" ); -?>
\ No newline at end of file diff --git a/maintenance/updateRestrictions.php b/maintenance/updateRestrictions.php index 6c8ffb5e..9503d0b7 100644 --- a/maintenance/updateRestrictions.php +++ b/maintenance/updateRestrictions.php @@ -25,9 +25,9 @@ function migrate_page_restrictions( $db ) { $end = $db->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); $blockStart = $start; $blockEnd = $start + BATCH_SIZE - 1; - $encodedExpiry = Block::decodeExpiry(''); + $encodedExpiry = 'infinity'; while ( $blockEnd <= $end ) { - $cond = "page_id BETWEEN $blockStart AND $blockEnd AND page_restrictions !=''"; + $cond = "page_id BETWEEN $blockStart AND $blockEnd AND page_restrictions !='' AND page_restrictions !='edit=:move='"; $res = $db->select( 'page', array('page_id', 'page_restrictions'), $cond, __FUNCTION__ ); $batch = array(); while ( $row = $db->fetchObject( $res ) ) { @@ -64,4 +64,4 @@ function migrate_page_restrictions( $db ) { } } -?> + diff --git a/maintenance/updateSearchIndex.php b/maintenance/updateSearchIndex.php index 9456be2a..a7f25624 100644 --- a/maintenance/updateSearchIndex.php +++ b/maintenance/updateSearchIndex.php @@ -53,4 +53,4 @@ $file = fopen( $posFile, 'w' ); fwrite( $file, $end ); fclose( $file ); -?> + diff --git a/maintenance/updateSpecialPages.php b/maintenance/updateSpecialPages.php index c7f9749d..424e20d9 100644 --- a/maintenance/updateSpecialPages.php +++ b/maintenance/updateSpecialPages.php @@ -101,4 +101,4 @@ foreach ( $wgQueryPages as $page ) { } } -?> + diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index 023a6b4b..3c972044 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -13,6 +13,8 @@ if ( !defined( 'MEDIAWIKI' ) ) { require_once 'convertLinks.inc'; require_once 'userDupes.inc'; require_once 'deleteDefaultMessages.php'; +# Extension updates +require_once( "$IP/includes/Hooks.php" ); $wgRenamedTables = array( # from to patch file @@ -35,6 +37,7 @@ $wgNewTables = array( array( 'querycache_info', 'patch-querycacheinfo.sql' ), array( 'filearchive', 'patch-filearchive.sql' ), array( 'querycachetwo', 'patch-querycachetwo.sql' ), + array( 'redirect', 'patch-redirect.sql' ), ); $wgNewFields = array( @@ -76,8 +79,19 @@ $wgNewFields = array( array( 'archive', 'ar_len', 'patch-ar_len.sql' ), array( 'revision', 'rev_parent_id', 'patch-rev_parent_id.sql' ), array( 'page_restrictions', 'pr_id', 'patch-page_restrictions_sortkey.sql' ), + array( 'ipblocks', 'ipb_block_email', 'patch-ipb_emailban.sql' ), + array( 'oldimage', 'oi_metadata', 'patch-oi_metadata.sql'), + array( 'archive', 'ar_page_id', 'patch-archive-page_id.sql'), + array( 'image', 'img_sha1', 'patch-img_sha1.sql' ), ); +# For extensions only, should be populated via hooks +# $wgDBtype should be checked to specifiy the proper file +$wgExtNewTables = array(); // table, dir +$wgExtNewFields = array(); // table, column, dir +$wgExtPGNewFields = array(); // table, column attributes; for PostgreSQL +$wgExtNewIndexes = array(); // table, index, dir + function rename_table( $from, $to, $patch ) { global $wgDatabase; if ( $wgDatabase->tableExists( $from ) ) { @@ -95,18 +109,22 @@ function rename_table( $from, $to, $patch ) { } } -function add_table( $name, $patch ) { +function add_table( $name, $patch, $fullpath=false ) { global $wgDatabase; if ( $wgDatabase->tableExists( $name ) ) { echo "...$name table already exists.\n"; } else { echo "Creating $name table..."; - dbsource( archive($patch), $wgDatabase ); + if( $fullpath ) { + dbsource( $patch, $wgDatabase ); + } else { + dbsource( archive($patch), $wgDatabase ); + } echo "ok\n"; } } -function add_field( $table, $field, $patch ) { +function add_field( $table, $field, $patch, $fullpath=false ) { global $wgDatabase; if ( !$wgDatabase->tableExists( $table ) ) { echo "...$table table does not exist, skipping new field patch\n"; @@ -114,7 +132,26 @@ function add_field( $table, $field, $patch ) { echo "...have $field field in $table table.\n"; } else { echo "Adding $field field to table $table..."; - dbsource( archive($patch) , $wgDatabase ); + if( $fullpath ) { + dbsource( $patch, $wgDatabase ); + } else { + dbsource( archive($patch), $wgDatabase ); + } + echo "ok\n"; + } +} + +function add_index( $table, $index, $patch, $fullpath=false ) { + global $wgDatabase; + if( $wgDatabase->indexExists( $table, $index ) ) { + echo "...$index key already set on $table table.\n"; + } else { + echo "Adding $index key to table $table... "; + if( $fullpath ) { + dbsource( $patch, $wgDatabase ); + } else { + dbsource( archive($patch), $wgDatabase ); + } echo "ok\n"; } } @@ -219,6 +256,38 @@ function do_logging_timestamp_index() { } } +function do_archive_user_index() { + global $wgDatabase; + if( $wgDatabase->indexExists( 'archive', 'usertext_timestamp' ) ) { + echo "...usertext,timestamp key on archive already exists.\n"; + } else { + echo "Adding usertext,timestamp key on archive table... "; + dbsource( archive("patch-archive-user-index.sql"), $wgDatabase ); + echo "ok\n"; + } +} + +function do_image_user_index() { + global $wgDatabase; + if( $wgDatabase->indexExists( 'image', 'img_usertext_timestamp' ) ) { + echo "...usertext,timestamp key on image already exists.\n"; + } else { + echo "Adding usertext,timestamp key on image table... "; + dbsource( archive("patch-image-user-index.sql"), $wgDatabase ); + echo "ok\n"; + } +} + +function do_oldimage_user_index() { + global $wgDatabase; + if( $wgDatabase->indexExists( 'oldimage', 'oi_usertext_timestamp' ) ) { + echo "...usertext,timestamp key on oldimage already exists.\n"; + } else { + echo "Adding usertext,timestamp key on oldimage table... "; + dbsource( archive("patch-oldimage-user-index.sql"), $wgDatabase ); + echo "ok\n"; + } +} function do_watchlist_update() { global $wgDatabase; @@ -311,7 +380,7 @@ function do_logging_encoding() { return; $logging = $wgDatabase->tableName( 'logging' ); $res = $wgDatabase->query( "SELECT log_title FROM $logging LIMIT 0" ); - $flags = explode( ' ', mysql_field_flags( $res, 0 ) ); + $flags = explode( ' ', mysql_field_flags( $res->result, 0 ) ); $wgDatabase->freeResult( $res ); if( in_array( 'binary', $flags ) ) { @@ -781,32 +850,26 @@ function do_templatelinks_update() { echo "Done. Please run maintenance/refreshLinks.php for a more thorough templatelinks update.\n"; } -# July 2006 -# Add ( rc_namespace, rc_user_text ) index [R. Church] +// Add index on ( rc_namespace, rc_user_text ) [Jul. 2006] +// Add index on ( rc_user_text, rc_timestamp ) [Nov. 2006] function do_rc_indices_update() { global $wgDatabase; echo( "Checking for additional recent changes indices...\n" ); - # See if we can find the index we want - $info = $wgDatabase->indexInfo( 'recentchanges', 'rc_ns_usertext', __METHOD__ ); - if( !$info ) { - # None, so create - echo( "...index on ( rc_namespace, rc_user_text ) not found; creating\n" ); - dbsource( archive( 'patch-recentchanges-utindex.sql' ) ); - } else { - # Index seems to exist - echo( "...index on ( rc_namespace, rc_user_text ) seems to be ok\n" ); - } - #Add (rc_user_text, rc_timestamp) index [A. Garrett], November 2006 - # See if we can find the index we want - $info = $wgDatabase->indexInfo( 'recentchanges', 'rc_user_text', __METHOD__ ); - if( !$info ) { - # None, so create - echo( "...index on ( rc_user_text, rc_timestamp ) not found; creating\n" ); - dbsource( archive( 'patch-rc_user_text-index.sql' ) ); - } else { - # Index seems to exist - echo( "...index on ( rc_user_text, rc_timestamp ) seems to be ok\n" ); + $indexes = array( + 'rc_ns_usertext' => 'patch-recentchanges-utindex.sql', + 'rc_user_text' => 'patch-rc_user_text-index.sql', + ); + + foreach( $indexes as $index => $patch ) { + $info = $wgDatabase->indexInfo( 'recentchanges', $index, __METHOD__ ); + if( !$info ) { + echo( "...index `{$index}` not found; adding..." ); + dbsource( archive( $patch ) ); + echo( "done.\n" ); + } else { + echo( "...index `{$index}` seems ok.\n" ); + } } } @@ -836,6 +899,14 @@ function do_backlinking_indices_update() { } } +function do_categorylinks_indices_update() { + echo( "Checking for categorylinks indices...\n" ); + if (!index_has_field('categorylinks', 'cl_sortkey', 'cl_from')) + { + dbsource( archive( 'patch-categorylinksindex.sql' ) ); + } +} + function do_stats_init() { // Sometimes site_stats table is not properly populated. global $wgDatabase; @@ -864,6 +935,8 @@ function purge_cache() { function do_all_updates( $shared = false, $purge = true ) { global $wgNewTables, $wgNewFields, $wgRenamedTables, $wgSharedDB, $wgDatabase, $wgDBtype, $IP; + wfRunHooks('LoadExtensionSchemaUpdates'); + $doUser = !$wgSharedDB || $shared; if ($wgDBtype === 'postgres') { @@ -889,6 +962,25 @@ function do_all_updates( $shared = false, $purge = true ) { } flush(); } + + global $wgExtNewTables, $wgExtNewFields, $wgExtNewIndexes; + # Add missing extension tables + foreach ( $wgExtNewTables as $tableRecord ) { + add_table( $tableRecord[0], $tableRecord[1], true ); + flush(); + } + # Add missing extension fields + foreach ( $wgExtNewFields as $fieldRecord ) { + if ( $fieldRecord[0] != 'user' || $doUser ) { + add_field( $fieldRecord[0], $fieldRecord[1], $fieldRecord[2], true ); + } + flush(); + } + # Add missing extension indexes + foreach ( $wgExtNewIndexes as $fieldRecord ) { + add_index( $fieldRecord[0], $fieldRecord[1], $fieldRecord[2], true ); + flush(); + } # Do schema updates which require special handling do_interwiki_update(); flush(); @@ -927,11 +1019,17 @@ function do_all_updates( $shared = false, $purge = true ) { do_rc_indices_update(); flush(); - add_table( 'redirect', 'patch-redirect.sql' ); - do_backlinking_indices_update(); flush(); + do_categorylinks_indices_update(); flush(); + do_restrictions_update(); flush (); + + do_archive_user_index(); flush (); + + do_image_user_index(); flush (); + + do_oldimage_user_index(); flush (); echo "Deleting old default messages (this may take a long time!)..."; flush(); deleteDefaultMessages(); @@ -1021,7 +1119,8 @@ function do_restrictions_update() { $wgDatabase->insert( 'page_restrictions', array ( 'pr_page' => $id, 'pr_type' => $type, 'pr_level' => $level, - 'pr_cascade' => 0 ), + 'pr_cascade' => 0, + 'pr_expiry' => 'infinity' ), __METHOD__ ); } } @@ -1219,7 +1318,10 @@ function do_postgres_updates() { $newcols = array( array("archive", "ar_len", "INTEGER"), + array("archive", "ar_page_id", "INTEGER"), + array("image", "img_sha1", "TEXT NOT NULL DEFAULT ''"), array("ipblocks", "ipb_anon_only", "CHAR NOT NULL DEFAULT '0'"), + array("ipblocks", "ipb_block_email", "CHAR NOT NULL DEFAULT '0'"), array("ipblocks", "ipb_create_account", "CHAR NOT NULL DEFAULT '1'"), array("ipblocks", "ipb_deleted", "INTEGER NOT NULL DEFAULT 0"), array("ipblocks", "ipb_enable_autoblock", "CHAR NOT NULL DEFAULT '1'"), @@ -1229,6 +1331,12 @@ function do_postgres_updates() { array("logging", "log_params", "TEXT"), array("mwuser", "user_editcount", "INTEGER"), array("mwuser", "user_newpass_time", "TIMESTAMPTZ"), + array("oldimage", "oi_deleted", "CHAR NOT NULL DEFAULT '0'"), + array("oldimage", "oi_metadata", "BYTEA NOT NULL DEFAULT ''"), + array("oldimage", "oi_media_type", "TEXT"), + array("oldimage", "oi_major_mime", "TEXT NOT NULL DEFAULT 'unknown'"), + array("oldimage", "oi_minor_mime", "TEXT NOT NULL DEFAULT 'unknown'"), + array("oldimage", "oi_sha1", "TEXT NOT NULL DEFAULT ''"), array("page_restrictions", "pr_id", "INTEGER NOT NULL UNIQUE DEFAULT nextval('pr_id_val')"), array("recentchanges", "rc_deleted", "INTEGER NOT NULL DEFAULT 0"), array("recentchanges", "rc_log_action", "TEXT"), @@ -1256,7 +1364,10 @@ function do_postgres_updates() { ); $newindexes = array( - array("revision", "rev_text_id_idx", "patch-rev_text_id_idx.sql") + array("archive", "archive_user_text", "(ar_user_text)"), + array("image", "img_sha1", "(img_sha1)"), + array("oldimage", "oi_sha1", "(oi_sha1)"), + array("revision", "rev_text_id_idx", "(rev_text_id)"), ); $newrules = array( @@ -1334,7 +1445,8 @@ function do_postgres_updates() { echo "... index $ni[1] on $ni[0] already exists\n"; continue; } - dbsource(archive($ni[2])); + $wgDatabase->query("CREATE INDEX $ni[1] ON $ni[0] $ni[2]"); + echo "create index $ni[1]\n"; } foreach ($newrules as $nr) { @@ -1383,7 +1495,36 @@ function do_postgres_updates() { } else echo "... archive.ar_deleted already exists\n"; + global $wgExtNewTables, $wgExtPGNewFields, $wgExtNewIndexes; + # Add missing extension tables + foreach ( $wgExtNewTables as $nt ) { + if ($wgDatabase->tableExists($nt[0])) { + echo "... table $nt[0] already exists\n"; + continue; + } + + echo "... create table $nt[0]\n"; + dbsource($nt[1]); + } + # Add missing extension fields + foreach ( $wgExtPGNewFields as $nc ) { + $fi = $wgDatabase->fieldInfo($nc[0], $nc[1]); + if (!is_null($fi)) { + echo "... column $nc[0].$nc[1] already exists\n"; + continue; + } + + echo "... add column $nc[0].$nc[1]\n"; + $wgDatabase->query("ALTER TABLE $nc[0] ADD $nc[1] $nc[2]"); + } + # Add missing extension indexes + foreach ( $wgExtNewIndexes as $ni ) { + if (pg_index_exists($ni[0], $ni[1])) { + echo "... index $ni[1] on $ni[0] already exists\n"; + continue; + } + dbsource($ni[2]); + } + return; } - -?> diff --git a/maintenance/upgrade1_5.php b/maintenance/upgrade1_5.php index a269c335..1c939a9b 100644 --- a/maintenance/upgrade1_5.php +++ b/maintenance/upgrade1_5.php @@ -21,4 +21,4 @@ $upgrade = new FiveUpgrade(); $step = isset( $options['step'] ) ? $options['step'] : null; $upgrade->upgrade( $step ); -?> + diff --git a/maintenance/userOptions.inc b/maintenance/userOptions.inc index 702ab715..b889e1b8 100644 --- a/maintenance/userOptions.inc +++ b/maintenance/userOptions.inc @@ -108,10 +108,25 @@ class userOptions { $user = User::newFromId( $id->user_id ); // Get the options and update stats - foreach( $defaultOptions as $name => $defaultValue ) { - $userValue = $user->getOption( $name ); - if( $userValue <> $defaultValue ) { - @$ret[$name][$userValue]++; + if( $this->mAnOption ) { + + if(!array_key_exists( $this->mAnOption, $defaultOptions ) ) { + print "Invalid user option. Use --list to see valid choices\n"; + exit; + } + + $userValue = $user->getOption( $this->mAnOption ); + if( $userValue <> $defaultOptions[$this->mAnOption] ) { + @$ret[$this->mAnOption][$userValue]++; + } + + } else { + + foreach( $defaultOptions as $name => $defaultValue ) { + $userValue = $user->getOption( $name ); + if( $userValue <> $defaultValue ) { + @$ret[$name][$userValue]++; + } } } } @@ -190,13 +205,13 @@ The new option is NOT validated. Usage: php userOptions.php --list - php userOptions.php <user option> --usage + php userOptions.php [user option] --usage php userOptions.php [options] <user option> --old <old value> --new <new value> Switchs: --list : list available user options and their default value - --usage <option name> : report statistics about an option + --usage : report all options statistics or just one if you specify it. --old <old value> : the value to look for --new <new value> : new value to update users with diff --git a/maintenance/userOptions.php b/maintenance/userOptions.php index f71d8e62..cb460b71 100644 --- a/maintenance/userOptions.php +++ b/maintenance/userOptions.php @@ -18,4 +18,4 @@ $uo = new userOptions( $options, $args ); $uo->run(); print "Done.\n"; -?> + diff --git a/maintenance/waitForSlave.php b/maintenance/waitForSlave.php index f41bdfc2..73a47364 100644 --- a/maintenance/waitForSlave.php +++ b/maintenance/waitForSlave.php @@ -13,4 +13,4 @@ if ( isset( $args[0] ) ) { wfWaitForSlaves(10); } -?> + diff --git a/maintenance/wikipedia-interwiki.sql b/maintenance/wikipedia-interwiki.sql index 38f33b9b..9e97967b 100644 --- a/maintenance/wikipedia-interwiki.sql +++ b/maintenance/wikipedia-interwiki.sql @@ -140,6 +140,7 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES ('mus','http://mus.wikipedia.org/wiki/$1',1), ('my','http://my.wikipedia.org/wiki/$1',1), ('nah','http://nah.wikipedia.org/wiki/$1',1), +('nan','http://zh-min-nan.wikipedia.org/wiki/$1',1), ('na','http://na.wikipedia.org/wiki/$1',1), ('nap','http://nap.wikipedia.org/wiki/$1',1), ('nb','http://nb.wikipedia.org/wiki/$1',1), @@ -226,6 +227,7 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES ('xh','http://xh.wikipedia.org/wiki/$1',1), ('yi','http://yi.wikipedia.org/wiki/$1',1), ('yo','http://yo.wikipedia.org/wiki/$1',1), +('yue','http://zh-yue.wikipedia.org/wiki/$1',1), ('za','http://za.wikipedia.org/wiki/$1',1), ('zh-cfr','http://zh-min-nan.wikipedia.org/wiki/$1',1), ('zh-classical','http://pam.wikipedia.org/wiki/$1',1), |