r45497 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r45496‎ | r45497 | r45498 >
Date:12:50, 7 January 2009
Author:tstarling
Status:deferred (Comments)
Tags:
Comment:
* Made it possible to set $wgLogo to false and have no logo. Made this the default, installer-configurable.
* Introduced $wgDeletedDirectory to replace obsolete $wgFileStore and installer-configurable
* Turned the "environment" page into a "welcome" page. Still needs some work to make it more welcoming.
* Refactored the getLabelled*() from InstallerDBType.php into WebInstaller where it can be useful for the WebInstaller pages
* Implemented pages "Name" and "Options". Finished the MySQL settings form.
* Implemented documentation pages which render files like README as wikitext.
* Removed MediaWiki copyright/license from navigation regions and put them on the welcome page.
* Split the bulk CSS and JS off to separate files
Modified paths:
  • /branches/new-installer/phase3/config/new-index.php (modified) (history)
  • /branches/new-installer/phase3/includes/DefaultSettings.php (modified) (history)
  • /branches/new-installer/phase3/includes/Setup.php (modified) (history)
  • /branches/new-installer/phase3/includes/SkinTemplate.php (modified) (history)
  • /branches/new-installer/phase3/includes/db/Database.php (modified) (history)
  • /branches/new-installer/phase3/includes/installer/Installer.php (modified) (history)
  • /branches/new-installer/phase3/includes/installer/InstallerDBType.php (modified) (history)
  • /branches/new-installer/phase3/includes/installer/MysqlInstaller.php (modified) (history)
  • /branches/new-installer/phase3/includes/installer/PostgresInstaller.php (modified) (history)
  • /branches/new-installer/phase3/includes/installer/SqliteInstaller.php (modified) (history)
  • /branches/new-installer/phase3/includes/installer/WebInstaller.php (modified) (history)
  • /branches/new-installer/phase3/includes/installer/WebInstallerOutput.php (modified) (history)
  • /branches/new-installer/phase3/languages/messages/MessagesEn.php (modified) (history)
  • /branches/new-installer/phase3/skins/MonoBook.php (modified) (history)
  • /branches/new-installer/phase3/skins/common/config-cc.css (added) (history)
  • /branches/new-installer/phase3/skins/common/config.css (added) (history)
  • /branches/new-installer/phase3/skins/common/config.js (added) (history)

Diff [purge]

Index: branches/new-installer/phase3/skins/common/config.js
@@ -0,0 +1,96 @@
 2+
 3+function showHelp(idx, show) {
 4+ var showDiv = document.getElementById( 'config-show-help-' + idx );
 5+ var hideDiv = document.getElementById( 'config-hide-help-' + idx );
 6+ var msgDiv = document.getElementById( 'config-help-message-' + idx );
 7+ if ( !showDiv || !hideDiv || !msgDiv ) return;
 8+ if ( show ) {
 9+ showDiv.style.display = 'none';
 10+ hideDiv.style.display = 'block';
 11+ msgDiv.style.display = 'block';
 12+ } else {
 13+ showDiv.style.display = 'block';
 14+ hideDiv.style.display = 'none';
 15+ msgDiv.style.display = 'none';
 16+ }
 17+}
 18+
 19+function hideAllDBs() {
 20+ for ( var i = 0; i < dbTypes.length; i++ ) {
 21+ elt = document.getElementById( 'DB_wrapper_' + dbTypes[i] );
 22+ if ( elt ) elt.style.display = 'none';
 23+ }
 24+}
 25+function showDBArea(type) {
 26+ hideAllDBs();
 27+ var div = document.getElementById('DB_wrapper_' + type);
 28+ if (div) div.style.display = 'block';
 29+}
 30+function resetDBArea() {
 31+ for ( var i = 0; i < dbTypes.length; i++ ) {
 32+ input = document.getElementById('DBType_' + dbTypes[i]);
 33+ if ( input && input.checked ) {
 34+ showDBArea( dbTypes[i] );
 35+ return;
 36+ }
 37+ }
 38+}
 39+function enableOrDisableControlArray( sourceID, targetIDs, enable ) {
 40+ var source = document.getElementById( sourceID );
 41+ var disabled = !!source.checked == enable ? '' : '1';
 42+ if ( !source ) {
 43+ return;
 44+ }
 45+ for ( var i = 0; i < targetIDs.length; i++ ) {
 46+ var elt = document.getElementById( targetIDs[i] );
 47+ if ( elt ) elt.disabled = disabled;
 48+ }
 49+}
 50+function enableControlArray( sourceID, targetIDs, enable ) {
 51+ enableOrDisableControlArray( sourceID, targetIDs, true );
 52+}
 53+function disableControlArray( sourceID, targetIDs ) {
 54+ enableOrDisableControlArray( sourceID, targetIDs, false );
 55+}
 56+
 57+function showControlArray( sourceID, targetIDs ) {
 58+ var source = document.getElementById( sourceID );
 59+ var show = !!source.checked == false ? '' : '1';
 60+ if ( !source ) {
 61+ return;
 62+ }
 63+ for ( var i = 0; i < targetIDs.length; i++ ) {
 64+ var elt = document.getElementById( targetIDs[i] );
 65+ if ( !elt ) continue;
 66+ if ( show ) {
 67+ elt.style.display = 'block';
 68+ } else {
 69+ elt.style.display = 'none';
 70+ }
 71+ }
 72+}
 73+wgSameNamespacePrefix = null;
 74+
 75+function setProjectNamespace() {
 76+ var radio = document.getElementById( 'config__NamespaceType_site-name' );
 77+ if ( radio == null ) return;
 78+ var li = radio.parentNode;
 79+ var labels = li.getElementsByTagName( 'label' );
 80+ if ( labels.length == 0 ) return;
 81+ var label = labels.item( 0 );
 82+
 83+ if ( wgSameNamespacePrefix == null ) {
 84+ wgSameNamespacePrefix = label.innerHTML;
 85+ }
 86+ var input = document.getElementById( 'config_wgSitename' );
 87+ if ( input == null ) return;
 88+ var value = input.value;
 89+ value = value.replace(/[\[\]\{\}|#<>%+? ]/g, '_');
 90+ value = value.replace(/&/, '&amp;');
 91+ value = value.replace(/__+/g, '_');
 92+ value = value.replace(/^_+/, '').replace(/_+$/, '');
 93+ value = value.substr(0, 1).toUpperCase()
 94+ + value.substr(1);
 95+ label.innerHTML = wgSameNamespacePrefix + value;
 96+}
 97+
Property changes on: branches/new-installer/phase3/skins/common/config.js
___________________________________________________________________
Added: svn:eol-style
198 + native
Index: branches/new-installer/phase3/skins/common/config.css
@@ -0,0 +1,146 @@
 2+.env-check {
 3+ font-size: 90%;
 4+ margin: 1em 0 1em 2.5em;
 5+}
 6+
 7+.config-section {
 8+ margin-top: 2em;
 9+}
 10+
 11+.config-label {
 12+ clear: left;
 13+ font-weight: bold;
 14+ width: 10em;
 15+ float: left;
 16+ text-align: right;
 17+ padding-right: 1em;
 18+ padding-top: .2em;
 19+}
 20+
 21+.config-input {
 22+ clear: left;
 23+ zoom: 100%; /* IE hack */
 24+}
 25+
 26+.config-page-wrapper {
 27+ padding: 0.5em;
 28+}
 29+
 30+.config-page-list {
 31+ float: right;
 32+ width: 12em;
 33+ border: 1px solid #aaa;
 34+ padding: 0.5em;
 35+ margin: 0.5em;
 36+}
 37+
 38+.config-page {
 39+ padding: 0.5em 2em 0.5em 2em;
 40+ /* 15em right margin to leave space for 12em page list */
 41+ margin: 0.5em 15em 0.5em 0.5em;
 42+ border: 1px solid #aaa;
 43+}
 44+
 45+.config-submit {
 46+ clear: left;
 47+ text-align: center;
 48+ padding: 1em;
 49+}
 50+
 51+.config-submit input {
 52+ margin-left: 0.5em;
 53+ margin-right: 0.5em;
 54+}
 55+
 56+.config-page-disabled {
 57+ color: #aaa;
 58+}
 59+
 60+.config-error-box {
 61+ border: 2px solid #f00;
 62+ margin: 0.4em;
 63+ clear: left;
 64+}
 65+
 66+.config-info-left {
 67+ margin: 7px;
 68+ float: left;
 69+ width: 35px;
 70+}
 71+
 72+.config-info-right {
 73+ margin: 0.5em 0.5em 0.5em 49px;
 74+ width: 30em;
 75+}
 76+
 77+.config-page-current {
 78+ font-weight: bold;
 79+}
 80+
 81+.config-help-wrapper {
 82+ clear: left;
 83+ margin: 0 0 2em 12em;
 84+ padding-top: 1em;
 85+}
 86+.config-show-help, .config-hide-help {
 87+ margin-left: 14em;
 88+}
 89+.config-help-message { display: none; }
 90+.config-hide-help { display: none; }
 91+
 92+.config-help-message {
 93+ font-size: 85%;
 94+}
 95+
 96+.config-message {
 97+ display: list-item;
 98+ line-height: 1.5em;
 99+ list-style-image: url(../skins/common/images/bullet.gif);
 100+ list-style-type: square;
 101+}
 102+
 103+.config-input-text {
 104+ width: 20em;
 105+ margin-right: 1em;
 106+}
 107+
 108+.config-input-check {
 109+ margin-left: 10em;
 110+}
 111+
 112+.error {
 113+ color: red;
 114+ background-color: #fff;
 115+ font-weight: bold;
 116+ left: 1em;
 117+ font-size: 100%;
 118+}
 119+
 120+.config-settings-block {
 121+ list-style-type: none;
 122+ list-style-image: none;
 123+ float: left;
 124+ margin: 0;
 125+ padding: 0;
 126+}
 127+
 128+.btn-install {
 129+ font-weight: bold;
 130+ font-size: 110%;
 131+ padding: .2em .3em;
 132+}
 133+
 134+.success-message {
 135+ font-weight: bold;
 136+ font-size: 110%;
 137+ color: green;
 138+}
 139+.success-box {
 140+ font-size: 130%;
 141+}
 142+
 143+.config-cc-wrapper {
 144+ clear: left;
 145+ /* If you change this height, also change it in WebInstaller_Options::submitCC() */
 146+ height: 54em;
 147+}
Property changes on: branches/new-installer/phase3/skins/common/config.css
___________________________________________________________________
Added: svn:eol-style
1148 + native
Index: branches/new-installer/phase3/skins/common/config-cc.css
@@ -0,0 +1,56 @@
 2+/**
 3+ * Copy of CC standard stylesheet, plus tweaks for iframe usage
 4+ */
 5+
 6+body {
 7+ margin:0px;
 8+ background:#eee;
 9+ font-family:verdana;
 10+ color:#333;
 11+}
 12+
 13+#main {
 14+ border:1px solid #D0D0D0;
 15+ background:#fff;
 16+ margin: 0.5em;
 17+}
 18+
 19+/* Looks like you have to specify the width of #menu
 20+or IE5 Mac stretches it all the way across the div, and
 21+Opera streches it half way. */
 22+
 23+#main #menu {
 24+ border-left:1px dotted #ccc;
 25+ /* border-bottom:1px solid #000;*/
 26+ float:right;
 27+ width:230px;
 28+ background:white;
 29+ margin:0px 0px 10px 10px;
 30+}
 31+
 32+td, h3, p,h1,pre {
 33+ margin:0px 20px 20px 20px;
 34+ font-size:11px;
 35+ line-height:140%;
 36+}
 37+
 38+.header {
 39+ padding-left: 10px;
 40+ padding-top:10px;
 41+}
 42+
 43+.nav {
 44+ padding-left:10px;
 45+ padding-bottom:10px;
 46+ font-size:11px;
 47+ margin-bottom:16px;
 48+}
 49+
 50+#menu p {
 51+ font-size:11px;
 52+}
 53+
 54+.dent {
 55+ margin-left:64px;
 56+}
 57+
Property changes on: branches/new-installer/phase3/skins/common/config-cc.css
___________________________________________________________________
Added: svn:eol-style
158 + native
Index: branches/new-installer/phase3/skins/MonoBook.php
@@ -131,8 +131,8 @@
132132 </div>
133133 </div>
134134 </div>
135 - <div id="column-one">
136 - <div id="p-cactions" class="portlet">
 135+ <div id="column-one" style="padding-top: <? echo intval($this->data['logoHeight'] + 25); ?>px">
 136+ <div id="p-cactions" class="portlet">
137137 <h5><?php $this->msg('views') ?></h5>
138138 <div class="pBody">
139139 <ul>
@@ -175,12 +175,17 @@
176176 </ul>
177177 </div>
178178 </div>
 179+<?php
 180+if ( strval( $this->data['logopath'] ) !== '' ):
 181+?>
179182 <div class="portlet" id="p-logo">
180183 <a style="background-image: url(<?php $this->text('logopath') ?>);" <?php
181184 ?>href="<?php echo htmlspecialchars($this->data['nav_urls']['mainpage']['href'])?>"<?php
182185 echo $skin->tooltipAndAccesskey('n-mainpage') ?>></a>
183186 </div>
184187 <script type="<?php $this->text('jsmimetype') ?>"> if (window.isMSIE55) fixalpha(); </script>
 188+<? endif; ?>
 189+
185190 <?php
186191 $sidebar = $this->data['sidebar'];
187192 if ( !isset( $sidebar['SEARCH'] ) ) $sidebar['SEARCH'] = true;
Index: branches/new-installer/phase3/includes/db/Database.php
@@ -1608,6 +1608,19 @@
16091609 }
16101610
16111611 /**
 1612+ * Convert a wildcard (as used in LIKE) to a regex
 1613+ * Slashes are escaped, slash terminators included
 1614+ */
 1615+ function likeToRegex( $wildcard ) {
 1616+ $r = preg_quote( $wildcard, '/' );
 1617+ $r = strtr( $r, array(
 1618+ '%' => '.*',
 1619+ '_' => '.'
 1620+ ) );
 1621+ return "/$r/s";
 1622+ }
 1623+
 1624+ /**
16121625 * Returns an appropriately quoted sequence value for inserting a new row.
16131626 * MySQL has autoincrement fields, so this is just NULL. But the PostgreSQL
16141627 * subclass will return an integer, and save the value for insertId()
Index: branches/new-installer/phase3/includes/Setup.php
@@ -42,8 +42,6 @@
4343 if( $wgStylePath === false ) $wgStylePath = "$wgScriptPath/skins";
4444 if( $wgStyleDirectory === false) $wgStyleDirectory = "$IP/skins";
4545
46 -if( $wgLogo === false ) $wgLogo = "$wgStylePath/common/images/wiki.png";
47 -
4846 if( $wgUploadPath === false ) $wgUploadPath = "$wgScriptPath/images";
4947 if( $wgUploadDirectory === false ) $wgUploadDirectory = "$IP/images";
5048
@@ -53,9 +51,9 @@
5452
5553 if( $wgReadOnlyFile === false ) $wgReadOnlyFile = "{$wgUploadDirectory}/lock_yBgMBwiR";
5654 if( $wgFileCacheDirectory === false ) $wgFileCacheDirectory = "{$wgUploadDirectory}/cache";
57 -
 55+if ( $wgDeletedDirectory === false ) $wgDeletedDirectory = "{$wgUploadDirectory}/deleted";
5856 if ( empty( $wgFileStore['deleted']['directory'] ) ) {
59 - $wgFileStore['deleted']['directory'] = "{$wgUploadDirectory}/deleted";
 57+ $wgFileStore['deleted']['directory'] = $wgDeletedDirectory;
6058 }
6159
6260 /**
Index: branches/new-installer/phase3/includes/installer/WebInstaller.php
@@ -20,13 +20,12 @@
2121 */
2222 var $pageSequence = array(
2323 'Language',
24 - 'Environment',
 24+ 'Welcome',
2525 'DBConnect',
2626 'Upgrade',
2727 'DBSettings',
28 - 'Identity',
29 - 'License',
30 - 'Email',
 28+ 'Name',
 29+ 'Options',
3130 'Install',
3231 'Complete',
3332 );
@@ -36,6 +35,9 @@
3736 */
3837 var $otherPages = array(
3938 'Restart',
 39+ 'Readme',
 40+ 'ReleaseNotes',
 41+ 'Copying',
4042 );
4143
4244 /**
@@ -56,12 +58,16 @@
5759 */
5860 var $showSessionWarning = false;
5961
 62+ var $helpId = 0;
 63+ var $tabIndex = 1;
 64+
 65+ var $currentPageName;
 66+
6067 /** Constructor */
6168 function __construct( $request ) {
6269 parent::__construct();
6370 $this->output = new WebInstallerOutput( $this );
6471 $this->request = $request;
65 - $this->internalDefaults['_UserLang'] = 'en';
6672 }
6773
6874 /**
@@ -74,6 +80,7 @@
7581 if ( isset( $session['settings'] ) ) {
7682 $this->settings = $session['settings'] + $this->settings;
7783 }
 84+
7885 if ( isset( $session['happyPages'] ) ) {
7986 $this->happyPages = $session['happyPages'];
8087 } else {
@@ -86,6 +93,19 @@
8794 }
8895 $lowestUnhappy = $this->getLowestUnhappy();
8996
 97+ # Special case for Creative Commons partner chooser box
 98+ if ( $this->request->getVal( 'SubmitCC' ) ) {
 99+ $page = $this->getPageByName( 'Options' );
 100+ $this->output->useShortHeader();
 101+ $page->submitCC();
 102+ return $this->finish();
 103+ }
 104+ if ( $this->request->getVal( 'ShowCC' ) ) {
 105+ $page = $this->getPageByName( 'Options' );
 106+ $this->output->useShortHeader();
 107+ $this->output->addHTML( $page->getCCDoneBox() );
 108+ return $this->finish();
 109+ }
90110
91111 # Get the page name
92112 $pageName = $this->request->getVal( 'page' );
@@ -134,6 +154,7 @@
135155 }
136156
137157 # Execute the page
 158+ $this->currentPageName = $page->getName();
138159 $this->startPageWrapper( $pageName );
139160 $result = $page->execute();
140161 $this->endPageWrapper();
@@ -204,8 +225,8 @@
205226 $args = func_get_args();
206227 array_shift( $args );
207228 $args = array_map( 'htmlspecialchars', $args );
208 - $msg = wfMsgReal( $msg, $args );
209 - $this->output->addHTML( "<div class=\"config-error-top\">\n$msg\n</div>\n" );
 229+ $msg = wfMsgReal( $msg, $args, false, false, false );
 230+ $this->output->addHTML( $this->getErrorBox( $msg ) );
210231 }
211232
212233 /**
@@ -276,6 +297,13 @@
277298 }
278299
279300 /**
 301+ * Get the next tabindex attribute value
 302+ */
 303+ function nextTabIndex() {
 304+ return $this->tabIndex++;
 305+ }
 306+
 307+ /**
280308 * Called by execute() before page output starts, to show a page list
281309 */
282310 function startPageWrapper( $currentPageName ) {
@@ -311,7 +339,9 @@
312340 if ( $enabled ) {
313341 $query = array( 'page' => $pageName );
314342 if ( !in_array( $pageName, $this->pageSequence ) ) {
315 - $query['lastPage'] = $currentPageName;
 343+ if ( in_array( $currentPageName, $this->pageSequence ) ) {
 344+ $query['lastPage'] = $currentPageName;
 345+ }
316346 $link = Xml::element( 'a',
317347 array(
318348 'href' => $this->getUrl( $query )
@@ -349,34 +379,42 @@
350380 }
351381
352382 /**
 383+ * Get HTML for an error box with an icon
 384+ * @param string $text Wikitext, get this with wfMsgNoTrans()
 385+ */
 386+ function getErrorBox( $text ) {
 387+ return $this->getInfoBox( $text, 'critical-32.png', 'config-error-box' );
 388+ }
 389+
 390+ /**
353391 * Get HTML for a warning box with an icon
 392+ * @param string $text Wikitext, get this with wfMsgNoTrans()
354393 */
355 - function getWarningBox( $msg ) {
356 - return $this->getInfoBox( $msg, 'warning-32.png' );
 394+ function getWarningBox( $text ) {
 395+ return $this->getInfoBox( $text, 'warning-32.png', 'config-warning-box' );
357396 }
358397
359398 /**
360399 * Get HTML for an info box with an icon
 400+ * @param string $text Wikitext, get this with wfMsgNoTrans()
 401+ * @param string $icon Icon name, file in skins/common/images
 402+ * @param string $class Additional class name to add to the wrapper div
361403 */
362 - function getInfoBox( $msg, $icon = 'info-32.png' ) {
363 - if ( is_array( $msg ) ) {
364 - $args = $msg;
365 - $msg = array_shift( $args );
366 - $text = wfMsgReal( $msg, $args, false, false, false );
367 - } else {
368 - $text = wfMsgNoTrans( $msg );
369 - }
370 - $s = "<div class=\"config-info\">\n" .
371 - "<div class=\"config-info-left\">\n" .
372 - Xml::element( 'img',
373 - array(
374 - 'src' => '../skins/common/images/' . $icon
375 - )
376 - ) . "\n" .
377 - "</div>\n" .
378 - "<div class=\"config-info-right\">\n" .
379 - $this->parse( $text ) .
380 - "</div></div>\n";
 404+ function getInfoBox( $text, $icon = 'info-32.png', $class = false ) {
 405+ $s =
 406+ "<div class=\"config-info $class\">\n" .
 407+ "<div class=\"config-info-left\">\n" .
 408+ Xml::element( 'img',
 409+ array(
 410+ 'src' => '../skins/common/images/' . $icon
 411+ )
 412+ ) . "\n" .
 413+ "</div>\n" .
 414+ "<div class=\"config-info-right\">\n" .
 415+ $this->parse( $text ) . "\n" .
 416+ "</div>\n" .
 417+ "<div style=\"clear: left;\"></div>\n" .
 418+ "</div>\n";
381419 return $s;
382420 }
383421
@@ -388,9 +426,25 @@
389427 $args = func_get_args();
390428 array_shift( $args );
391429 $args = array_map( 'htmlspecialchars', $args );
392 - return "<div class=\"config-desc\">\n" .
393 - $this->parse( wfMsgReal( $msg, $args, false, false, false ) ) .
394 - "</div>\n";
 430+ $text = wfMsgReal( $msg, $args, false, false, false );
 431+ $html = $this->parse( $text, true );
 432+ $id = $this->helpId++;
 433+
 434+ return
 435+ "<div class=\"config-help-wrapper\">\n" .
 436+ "<div class=\"config-show-help\" id=\"config-show-help-$id\">\n" .
 437+ Xml::openElement( 'a', array( 'href' => "javascript:showHelp($id,true)" ) ) .
 438+ "<img src=\"../skins/common/images/help-22.png\"/>&nbsp;&nbsp;" .
 439+ wfMsgHtml( 'config-show-help' ) .
 440+ "</a></div>\n" .
 441+ "<div class=\"config-help-message\" id=\"config-help-message-$id\">\n" .
 442+ $html.
 443+ "</div>\n" .
 444+ "<div class=\"config-hide-help\" id=\"config-hide-help-$id\">\n" .
 445+ Xml::openElement( 'a', array( 'href' => "javascript:showHelp($id,false)" ) ) .
 446+ "<img src=\"../skins/common/images/help-22.png\"/>&nbsp;&nbsp;" .
 447+ wfMsgHtml( 'config-hide-help' ) .
 448+ "</a></div>\n</div>\n";
395449 }
396450
397451 /**
@@ -416,64 +470,244 @@
417471 }
418472
419473 /**
420 - * Get a label element using a message name
 474+ * Label a control by wrapping a config-input div around it and putting a
 475+ * label before it
421476 */
422 - function getLabel( $msg, $for ) {
423 - return Xml::element( 'label',
424 - array( 'for' => $for, 'class' => 'config-label' ),
425 - wfMsg( $msg ) ) . "\n";
 477+ function label( $msg, $forId, $contents ) {
 478+ if ( strval( $msg ) == '' ) {
 479+ $labelText = '&nbsp;';
 480+ } else {
 481+ $labelText = wfMsgHtml( $msg );
 482+ }
 483+ return
 484+ "<div class=\"config-input\">\n" .
 485+ Xml::tags( 'label',
 486+ array( 'for' => $forId, 'class' => 'config-label' ),
 487+ $labelText ) . "\n" .
 488+ $contents .
 489+ "</div>\n";
426490 }
427491
428492 /**
429 - * Get a text box
 493+ * Get a labelled text box to configure a variable
 494+ * @param array $params
 495+ * Parameters are:
 496+ * var: The variable to be configured (required)
 497+ * label: The message name for the label (required)
 498+ * attribs: Additional attributes for the input element (optional)
 499+ * controlName: The name for the input element (optional)
 500+ * value: The current value of the variable (optional)
430501 */
431 - function getTextBox( $name, $value = '', $type = 'text' ) {
432 - return Xml::element( 'input',
433 - array(
434 - 'type' => $type,
435 - 'name' => $name,
436 - 'id' => $name,
437 - 'value' => $value,
438 - 'class' => 'config-input-text',
439 - )
440 - );
 502+ function getTextBox( $params ) {
 503+ if ( !isset( $params['controlName'] ) ) {
 504+ $params['controlName'] = 'config_' . $params['var'];
 505+ }
 506+ if ( !isset( $params['value'] ) ) {
 507+ $params['value'] = $this->getVar( $params['var'] );
 508+ }
 509+ if ( !isset( $params['attribs'] ) ) {
 510+ $params['attribs'] = array();
 511+ }
 512+ return
 513+ $this->label(
 514+ $params['label'],
 515+ $params['controlName'],
 516+ Xml::input(
 517+ $params['controlName'],
 518+ 30, // intended to be overridden by CSS
 519+ $params['value'],
 520+ $params['attribs'] + array(
 521+ 'id' => $params['controlName'],
 522+ 'class' => 'config-input-text',
 523+ 'tabindex' => $this->nextTabIndex()
 524+ )
 525+ )
 526+ );
441527 }
442528
443529 /**
444 - * Get a checkbox
 530+ * Get a labelled password box to configure a variable
 531+ * Implements password hiding
 532+ * @param array $params
 533+ * Parameters are:
 534+ * var: The variable to be configured (required)
 535+ * label: The message name for the label (required)
 536+ * attribs: Additional attributes for the input element (optional)
 537+ * controlName: The name for the input element (optional)
 538+ * value: The current value of the variable (optional)
445539 */
446 - function getCheckBox( $name, $value, $attribs ) {
447 - return Xml::element( 'input',
448 - $attribs + array(
449 - 'type' => 'checkbox',
450 - 'name' => $name,
451 - 'id' => $name,
452 - 'checked' => $value ? '1' : '',
453 - 'class' => 'config-input-text',
454 - )
455 - );
 540+ function getPasswordBox( $params ) {
 541+ if ( !isset( $params['value'] ) ) {
 542+ $params['value'] = $this->getVar( $params['var'] );
 543+ }
 544+ if ( !isset( $params['attribs'] ) ) {
 545+ $params['attribs'] = array();
 546+ }
 547+ $params['value'] = $this->getFakePassword( $params['value'] );
 548+ $params['attribs']['type'] = 'password';
 549+ return $this->getTextBox( $params );
456550 }
457551
458552 /**
 553+ * Get a labelled checkbox to configure a boolean variable
 554+ * @param array $params
 555+ * Parameters are:
 556+ * var: The variable to be configured (required)
 557+ * label: The message name for the label (required)
 558+ * attribs: Additional attributes for the input element (optional)
 559+ * controlName: The name for the input element (optional)
 560+ * value: The current value of the variable (optional)
 561+ */
 562+ function getCheckBox( $params ) {
 563+ if ( !isset( $params['controlName'] ) ) {
 564+ $params['controlName'] = 'config_' . $params['var'];
 565+ }
 566+ if ( !isset( $params['value'] ) ) {
 567+ $params['value'] = $this->getVar( $params['var'] );
 568+ }
 569+ if ( !isset( $params['attribs'] ) ) {
 570+ $params['attribs'] = array();
 571+ }
 572+ return
 573+ "<div class=\"config-input-check\">\n" .
 574+ "<label>\n" .
 575+ Xml::check(
 576+ $params['controlName'],
 577+ $params['value'],
 578+ $params['attribs'] + array(
 579+ 'id' => $params['controlName'],
 580+ 'class' => 'config-input-text',
 581+ 'tabindex' => $this->nextTabIndex(),
 582+ )
 583+ ) .
 584+ $this->parse( wfMsg( $params['label'] ) ) . "\n" .
 585+ "</label>\n" .
 586+ "</div>\n";
 587+ }
 588+
 589+ /**
 590+ * Get a set of labelled radio buttons
 591+ *
 592+ * @param array $params
 593+ * Parameters are:
 594+ * var: The variable to be configured (required)
 595+ * label: The message name for the label (required)
 596+ * itemLabelPrefix: The message name prefix for the item labels (required)
 597+ * values: List of allowed values (required)
 598+ * itemAttribs Array of attribute arrays, outer key is the value name (optional)
 599+ * commonAttribs Attribute array applied to all items
 600+ * controlName: The name for the input element (optional)
 601+ * value: The current value of the variable (optional)
 602+ */
 603+ function getRadioSet( $params ) {
 604+ if ( !isset( $params['controlName'] ) ) {
 605+ $params['controlName'] = 'config_' . $params['var'];
 606+ }
 607+ if ( !isset( $params['value'] ) ) {
 608+ $params['value'] = $this->getVar( $params['var'] );
 609+ }
 610+ if ( !isset( $params['label'] ) ) {
 611+ $label = '';
 612+ } else {
 613+ $label = $this->parse( wfMsgNoTrans( $params['label'] ) );
 614+ }
 615+ $s = "<label class=\"config-label\">\n" .
 616+ $label .
 617+ "</label>\n" .
 618+ "<ul class=\"config-settings-block\">\n";
 619+ foreach ( $params['values'] as $value ) {
 620+ $itemAttribs = array();
 621+ if ( isset( $params['commonAttribs'] ) ) {
 622+ $itemAttribs = $params['commonAttribs'];
 623+ }
 624+ if ( isset( $params['itemAttribs'][$value] ) ) {
 625+ $itemAttribs = $params['itemAttribs'][$value] + $itemAttribs;
 626+ }
 627+ $checked = $value == $params['value'];
 628+ $id = $params['controlName'] . '_' . $value;
 629+ $itemAttribs['id'] = $id;
 630+ $itemAttribs['tabindex'] = $this->nextTabIndex();
 631+ $s .=
 632+ '<li>' .
 633+ Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
 634+ '&nbsp;' .
 635+ Xml::tags( 'label', array( 'for' => $id ), $this->parse(
 636+ wfMsgNoTrans( $params['itemLabelPrefix'] . strtolower( $value ) )
 637+ ) ) .
 638+ "</li>\n";
 639+ }
 640+ $s .= "</ul>\n";
 641+ return $s;
 642+ }
 643+
 644+ /**
459645 * Output an error box using a Status object
460646 */
461647 function showStatusErrorBox( $status ) {
462648 $text = $status->getWikiText();
463 - $this->parent->output->addWikiText(
464 - "<div class=\"config-error-top\">\n" .
465 - $text .
466 - "</div>"
467 - );
 649+ $this->output->addHTML( $this->getErrorBox( $text ) );
468650 }
469651
470652 function showStatusError( $status ) {
471653 $text = $status->getWikiText();
472 - $this->parent->output->addWikiText(
 654+ $this->output->addWikiText(
473655 "<div class=\"config-message\">\n" .
474656 $text .
475657 "</div>"
476658 );
477659 }
 660+
 661+ /**
 662+ * Convenience function to set variables based on form data.
 663+ * Assumes that variables containing "password" in the name are (potentially
 664+ * fake) passwords.
 665+ * @param array $varNames
 666+ * @param string $prefix The prefix added to variables to obtain form names
 667+ */
 668+ function setVarsFromRequest( $varNames, $prefix = 'config_' ) {
 669+ $newValues = array();
 670+ foreach ( $varNames as $name ) {
 671+ $value = $this->request->getVal( $prefix . $name );
 672+ $newValues[$name] = $value;
 673+ if ( $value === null ) {
 674+ // Checkbox?
 675+ $this->setVar( $name, false );
 676+ } else {
 677+ if ( stripos( $name, 'password' ) !== false ) {
 678+ $this->setPassword( $name, $value );
 679+ } else {
 680+ $this->setVar( $name, $value );
 681+ }
 682+ }
 683+ }
 684+ return $newValues;
 685+ }
 686+
 687+ /**
 688+ * Get the starting tags of a fieldset
 689+ * @param string $legend Message name
 690+ */
 691+ function getFieldsetStart( $legend ) {
 692+ return "\n<fieldset><legend>" . wfMsgHtml( $legend ) . "</legend>\n";
 693+ }
 694+
 695+ /**
 696+ * Get the end tag of a fieldset
 697+ */
 698+ function getFieldsetEnd() {
 699+ return "</fieldset>\n";
 700+ }
 701+
 702+ /**
 703+ * Helper for Installer::docLink()
 704+ */
 705+ function getDocUrl( $page ) {
 706+ $url = "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page );
 707+ if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
 708+ $url .= '&lastPage=' . urlencode( $this->currentPageName );
 709+ }
 710+ return $url;
 711+ }
478712 }
479713
480714 class WebInstallerPage {
@@ -503,14 +737,21 @@
504738 if ( $continue ) {
505739 // Fake submit button for enter keypress
506740 $s .= Xml::submitButton( wfMsg( "config-$continue" ),
507 - array( 'name' => "enter-$continue", 'style' => 'display:none' ) );
 741+ array( 'name' => "enter-$continue", 'style' => 'display:none' ) ) . "\n";
508742 }
509743 if ( $id !== 0 ) {
510 - $s .= Xml::submitButton( wfMsg( 'config-back' ), array( 'name' => 'submit-back' ) );
 744+ $s .= Xml::submitButton( wfMsg( 'config-back' ),
 745+ array(
 746+ 'name' => 'submit-back',
 747+ 'tabindex' => $this->parent->nextTabIndex()
 748+ ) ) . "\n";
511749 }
512750 if ( $continue ) {
513751 $s .= Xml::submitButton( wfMsg( "config-$continue" ),
514 - array( 'name' => "submit-$continue" ) );
 752+ array(
 753+ 'name' => "submit-$continue",
 754+ 'tabindex' => $this->parent->nextTabIndex(),
 755+ ) ) . "\n";
515756 }
516757 $s .= "</div></form></div>\n";
517758 $this->parent->output->addHTML( $s );
@@ -533,6 +774,14 @@
534775 $this->endForm();
535776 }
536777 }
 778+
 779+ function getVar( $var ) {
 780+ return $this->parent->getVar( $var );
 781+ }
 782+
 783+ function setVar( $name, $value ) {
 784+ $this->parent->setVar( $name, $value );
 785+ }
537786 }
538787
539788 class WebInstaller_Language extends WebInstallerPage {
@@ -544,12 +793,12 @@
545794
546795 if ( $r->wasPosted() ) {
547796 # Do session test
 797+ $lifetime = intval( ini_get( 'session.gc_maxlifetime' ) );
 798+ if ( !$lifetime ) {
 799+ $lifetime = 1440; // PHP default
 800+ }
548801 if ( $this->parent->getSession( 'test' ) === null ) {
549802 $requestTime = $r->getVal( 'LanguageRequestTime' );
550 - $lifetime = intval( ini_get( 'session.gc_maxlifetime' ) );
551 - if ( !$lifetime ) {
552 - $lifetime = 1440;
553 - }
554803 if ( !$requestTime ) {
555804 // The most likely explanation is that the user was knocked back
556805 // from another page on POST due to session expiry
@@ -563,26 +812,26 @@
564813 } else {
565814 $languages = Language::getLanguageNames();
566815 if ( isset( $languages[$userLang] ) ) {
567 - $this->parent->setVar( '_UserLang', $userLang );
 816+ $this->setVar( '_UserLang', $userLang );
568817 }
569818 if ( isset( $languages[$contLang] ) ) {
570 - $this->parent->setVar( 'wgLanguageCode', $contLang );
 819+ $this->setVar( 'wgLanguageCode', $contLang );
571820 }
572821 return 'continue';
573822 }
574823 } elseif ( $this->parent->showSessionWarning ) {
575824 # The user was knocked back from another page to the start
576825 # This probably indicates a session expiry
577 - $this->parent->showError( 'config-session-expired' );
 826+ $this->parent->showError( 'config-session-expired', $wgLang->formatTimePeriod( $lifetime ) );
578827 }
579828
580829 $this->parent->setSession( 'test', true );
581830
582831 if ( !isset( $languages[$userLang] ) ) {
583 - $userLang = $this->parent->getVar( '_UserLang', 'en' );
 832+ $userLang = $this->getVar( '_UserLang', 'en' );
584833 }
585834 if ( !isset( $languages[$contLang] ) ) {
586 - $contLang = $this->parent->getVar( 'wgLanguageCode', 'en' );
 835+ $contLang = $this->getVar( 'wgLanguageCode', 'en' );
587836 }
588837 $this->startForm();
589838 $s =
@@ -601,30 +850,30 @@
602851 * Get a <select> for selecting languages
603852 */
604853 function getLanguageSelector( $name, $label, $selectedCode ) {
605 - $s = "<div class=\"config-input\">\n" .
606 - $this->parent->getLabel( $label, $name ) .
607 - Xml::openElement( 'select', array( 'id' => $name, 'name' => $name ) ) . "\n";
 854+ $s = Xml::openElement( 'select', array( 'id' => $name, 'name' => $name ) ) . "\n";
608855
609856 $languages = Language::getLanguageNames();
610857 ksort( $languages );
611858 foreach ( $languages as $code => $name ) {
612859 $s .= "\n" . Xml::option( "$code - $name", $code, $code == $selectedCode );
613860 }
614 - $s .= "\n</select>\n</div>\n";
615 - return $s;
 861+ $s .= "\n</select>\n";
 862+ return $this->parent->label( $label, $name, $s );
616863 }
617864
618865 }
619866
620 -class WebInstaller_Environment extends WebInstallerPage {
 867+class WebInstaller_Welcome extends WebInstallerPage {
621868 function execute() {
622869 if ( $this->parent->request->wasPosted() ) {
623 - if ( $this->parent->getVar( '_Environment' ) ) {
 870+ if ( $this->getVar( '_Environment' ) ) {
624871 return 'continue';
625872 }
626873 }
 874+ $this->parent->output->addWikiText( wfMsgNoTrans( 'config-welcome' ) );
627875 $status = $this->parent->doEnvironmentChecks();
628876 if ( $status ) {
 877+ $this->parent->output->addWikiText( wfMsgNoTrans( 'config-copyright' ) );
629878 $this->startForm();
630879 $this->endForm();
631880 }
@@ -634,30 +883,22 @@
635884 class WebInstaller_DBConnect extends WebInstallerPage {
636885 function execute() {
637886 $r = $this->parent->request;
638 - if ( $this->parent->request->wasPosted() ) {
 887+ if ( $r->wasPosted() ) {
639888 $status = $this->submit();
640889 if ( $status->isGood() ) {
641 - $this->parent->setVar( '_UpgradeDone', false );
 890+ $this->setVar( '_UpgradeDone', false );
642891 return 'continue';
643892 } else {
644 - $error = $status->getWikiText();
645 - $this->parent->output->addWikiText(
646 - "<div class=\"config-error-top\">\n" .
647 - $error .
648 - "</div>"
649 - );
 893+ $this->parent->showStatusErrorBox( $status );
650894 }
651895 }
652896
653897
654898 $this->startForm();
655899
656 - $types = "<label class=\"config-label\">" .
657 - wfMsg( 'config-db-type' ) .
658 - "</label>" .
659 - "<ul class=\"config-settings-block\">\n";
 900+ $types = "<ul class=\"config-settings-block\">\n";
660901 $settings = '';
661 - $defaultType = $this->parent->getVar( 'wgDBtype' );
 902+ $defaultType = $this->getVar( 'wgDBtype' );
662903 foreach ( $this->parent->getDBTypes() as $type ) {
663904 $installer = $this->parent->getDBInstaller( $type );
664905 $encType = Xml::encodeJsVar( $type );
@@ -683,9 +924,9 @@
684925 $encType = Xml::encodeJsVar( $defaultType );
685926
686927 $this->parent->output->addHTML(
687 - $types .
 928+ $this->parent->label( 'config-db-type', false, $types ) .
688929 $settings .
689 - "<script>resetDBArea();</script>\n"
 930+ "<script type=\"text/javascript\">resetDBArea();</script>\n"
690931 );
691932
692933 $this->endForm();
@@ -694,7 +935,7 @@
695936 function submit() {
696937 $r = $this->parent->request;
697938 $type = $r->getVal( 'DBType' );
698 - $this->parent->setVar( 'wgDBtype', $type );
 939+ $this->setVar( 'wgDBtype', $type );
699940 $installer = $this->parent->getDBInstaller( $type );
700941 if ( !$installer ) {
701942 return Status::newFatal( 'config-invalid-db-type' );
@@ -705,7 +946,7 @@
706947
707948 class WebInstaller_Upgrade extends WebInstallerPage {
708949 function execute() {
709 - if ( $this->parent->getVar( '_UpgradeDone' ) ) {
 950+ if ( $this->getVar( '_UpgradeDone' ) ) {
710951 if ( $this->parent->request->wasPosted() ) {
711952 // Done message acknowledged
712953 return 'continue';
@@ -720,31 +961,16 @@
721962
722963 // wgDBtype is generally valid here because otherwise the previous page
723964 // (connect) wouldn't have declared its happiness
724 - $type = $this->parent->getVar( 'wgDBtype' );
 965+ $type = $this->getVar( 'wgDBtype' );
725966 $installer = $this->parent->getDBInstaller( $type );
726967
727 - // There's no guarantee the connection will still succeed though
728 - $conn = $installer->getConnection();
729 - if ( $conn instanceof Status ) {
730 - $this->startForm();
731 - $this->showStatusErrorBox( $conn );
732 - $this->endForm();
733 - return 'output';
734 - }
735 -
736 - $ok = $conn->selectDB( $this->parent->getVar( 'wgDBname' ) );
737 - if ( !$ok ) {
738 - // No DB exists yet
 968+ if ( !$installer->needsUpgrade() ) {
739969 return 'skip';
740970 }
741 - if ( !$conn->tableExists( 'cur' ) && !$conn->tableExists( 'revision' ) ) {
742 - // Nothing to upgrade
743 - return 'skip';
744 - }
745971
746972 if ( $this->parent->request->wasPosted() ) {
747973 if ( true || $installer->doUpgrade() ) {
748 - $this->parent->setVar( '_UpgradeDone', true );
 974+ $this->setVar( '_UpgradeDone', true );
749975 $this->showDoneMessage();
750976 return 'output';
751977 }
@@ -752,7 +978,7 @@
753979
754980 $this->startForm();
755981 $this->parent->output->addHTML( $this->parent->getInfoBox(
756 - array( 'config-can-upgrade', $GLOBALS['wgVersion'] ) ) );
 982+ wfMsgNoTrans( 'config-can-upgrade', $GLOBALS['wgVersion'] ) ) );
757983 $this->endForm();
758984 }
759985
@@ -760,11 +986,10 @@
761987 $this->startForm();
762988 $this->parent->output->addHTML(
763989 $this->parent->getInfoBox(
764 - array(
765 - 'config-upgrade-done',
 990+ wfMsgNoTrans( 'config-upgrade-done',
766991 $GLOBALS['wgServer'] .
767 - $this->parent->getVar( 'wgScriptPath' ) . '/index' .
768 - $this->parent->getVar( 'wgScriptExtension' )
 992+ $this->getVar( 'wgScriptPath' ) . '/index' .
 993+ $this->getVar( 'wgScriptExtension' )
769994 ), 'tick-32.png'
770995 )
771996 );
@@ -774,11 +999,25 @@
7751000
7761001 class WebInstaller_DBSettings extends WebInstallerPage {
7771002 function execute() {
778 - $installer = $this->parent->getDBInstaller( $this->parent->getVar( 'wgDBtype' ) );
 1003+ $installer = $this->parent->getDBInstaller( $this->getVar( 'wgDBtype' ) );
 1004+
 1005+ $r = $this->parent->request;
 1006+ if ( $r->wasPosted() ) {
 1007+ $status = $installer->submitSettingsForm();
 1008+ if ( $status === false ) {
 1009+ return 'skip';
 1010+ } elseif ( $status->isGood() ) {
 1011+ return 'continue';
 1012+ } else {
 1013+ $this->parent->showStatusErrorBox( $status );
 1014+ }
 1015+ }
 1016+
7791017 $form = $installer->getSettingsForm();
7801018 if ( $form === false ) {
7811019 return 'skip';
7821020 }
 1021+
7831022 $this->startForm();
7841023 $this->parent->output->addHTML( $form );
7851024 $this->endForm();
@@ -786,12 +1025,353 @@
7871026
7881027 }
7891028
790 -class WebInstaller_Identity extends WebInstallerPage {
 1029+class WebInstaller_Name extends WebInstallerPage {
 1030+ function execute() {
 1031+ $r = $this->parent->request;
 1032+ if ( $r->wasPosted() ) {
 1033+ if ( $this->submit() ) {
 1034+ return 'continue';
 1035+ }
 1036+ }
 1037+
 1038+ $this->startForm();
 1039+
 1040+ if ( $this->getVar( 'wgSitename' ) == $GLOBALS['wgSitename'] ) {
 1041+ $this->setVar( 'wgSitename', '' );
 1042+ }
 1043+ $js = 'enableControlArray("config__NamespaceType_other", ["config_wgMetaNamespace"])';
 1044+ $attribs = array( 'onclick' => $js );
 1045+
 1046+ $this->parent->output->addHTML(
 1047+ $this->parent->getTextBox( array(
 1048+ 'var' => 'wgSitename',
 1049+ 'label' => 'config-site-name',
 1050+ 'attribs' => array(
 1051+ 'onkeyup' => 'setProjectNamespace();',
 1052+ 'onchange' => 'setProjectNamespace();'
 1053+ )
 1054+ ) ) .
 1055+ $this->parent->getHelpBox( 'config-site-name-help' ) .
 1056+ $this->parent->getRadioSet( array(
 1057+ 'var' => '_NamespaceType',
 1058+ 'label' => 'config-project-namespace',
 1059+ 'itemLabelPrefix' => 'config-ns-',
 1060+ 'values' => array( 'site-name', 'generic', 'other' ),
 1061+ 'commonAttribs' => $attribs,
 1062+ ) ) .
 1063+ $this->parent->getTextBox( array(
 1064+ 'var' => 'wgMetaNamespace',
 1065+ 'label' => '',
 1066+ ) ) .
 1067+ "<script type=\"text/javascript\">\nsetProjectNamespace();\n$js\n</script>\n" .
 1068+ $this->parent->getHelpBox( 'config-project-namespace-help' ) .
 1069+ $this->parent->getFieldsetStart( 'config-admin-box' ) .
 1070+ $this->parent->getTextBox( array(
 1071+ 'var' => '_AdminName',
 1072+ 'label' => 'config-admin-name'
 1073+ ) ) .
 1074+ $this->parent->getPasswordBox( array(
 1075+ 'var' => '_AdminPassword',
 1076+ 'label' => 'config-admin-password',
 1077+ ) ) .
 1078+ $this->parent->getPasswordBox( array(
 1079+ 'var' => '_AdminPassword2',
 1080+ 'label' => 'config-admin-password-confirm'
 1081+ ) ) .
 1082+ $this->parent->getHelpBox( 'config-admin-help' ) .
 1083+ $this->parent->getTextBox( array(
 1084+ 'var' => '_AdminEmail',
 1085+ 'label' => 'config-admin-email'
 1086+ ) ) .
 1087+ $this->parent->getHelpBox( 'config-admin-email-help' ) .
 1088+ $this->parent->getCheckBox( array(
 1089+ 'var' => '_Subscribe',
 1090+ 'label' => 'config-subscribe'
 1091+ ) ) .
 1092+ $this->parent->getHelpBox( 'config-subscribe-help' ) .
 1093+ $this->parent->getFieldsetEnd() .
 1094+ $this->parent->getInfoBox( wfMsg( 'config-almost-done' ) ) .
 1095+ $this->parent->getRadioSet( array(
 1096+ 'var' => '_SkipOptional',
 1097+ 'itemLabelPrefix' => 'config-optional-',
 1098+ 'values' => array( 'continue', 'skip' )
 1099+ ) )
 1100+ );
 1101+
 1102+ $this->endForm();
 1103+ return 'output';
 1104+ }
 1105+
 1106+ function submit() {
 1107+ $retVal = true;
 1108+ $this->parent->setVarsFromRequest( array( 'wgSitename', '_NamespaceType',
 1109+ '_AdminName', '_AdminPassword', '_AdminPassword2', '_AdminEmail',
 1110+ '_Subscribe', '_SkipOptional' ) );
 1111+
 1112+ // Validate site name
 1113+ if ( strval( $this->getVar( 'wgSitename' ) ) === '' ) {
 1114+ $this->parent->showError( 'config-site-name-blank' );
 1115+ $retVal = false;
 1116+ }
 1117+
 1118+ // Fetch namespace
 1119+ $nsType = $this->getVar( '_NamespaceType' );
 1120+ if ( $nsType == 'site-name' ) {
 1121+ $name = $this->getVar( 'wgSitename' );
 1122+ // Sanitize for namespace
 1123+ // This algorithm should match the JS one in WebInstallerOutput.php
 1124+ $name = preg_replace( '/[\[\]\{\}|#<>%+? ]/', '_', $name );
 1125+ $name = str_replace( '&', '&amp;', $name );
 1126+ $name = preg_replace( '/__+/', '_', $name );
 1127+ $name = ucfirst( trim( $name, '_' ) );
 1128+ } elseif ( $nsType == 'generic' ) {
 1129+ $name = wfMsg( 'config-ns-generic' );
 1130+ } else { // other
 1131+ $name = $this->getVar( 'wgMetaNamespace' );
 1132+ }
 1133+
 1134+ // Validate namespace
 1135+ if ( strpos( $name, ':' ) !== false ) {
 1136+ $good = false;
 1137+ } else {
 1138+ // Title-style validation
 1139+ $title = Title::newFromText( $name );
 1140+ if ( !$title ) {
 1141+ $good = false;
 1142+ } else {
 1143+ $name = $title->getDBkey();
 1144+ $good = true;
 1145+ }
 1146+ }
 1147+ if ( !$good ) {
 1148+ $this->parent->showError( 'config-ns-invalid', $name );
 1149+ $retVal = false;
 1150+ }
 1151+ $this->setVar( 'wgMetaNamespace', $name );
 1152+
 1153+ // Validate username for creation
 1154+ $name = $this->getVar( '_AdminName' );
 1155+ if ( strval( $name ) === '' ) {
 1156+ $this->parent->showError( 'config-admin-name-blank' );
 1157+ $cname = $name;
 1158+ $retVal = false;
 1159+ } else {
 1160+ $cname = User::getCanonicalName( $name, 'creatable' );
 1161+ if ( $cname === false ) {
 1162+ $this->parent->showError( 'config-admin-name-invalid', $name );
 1163+ $retVal = false;
 1164+ } else {
 1165+ $this->setVar( '_AdminName', $cname );
 1166+ }
 1167+ }
 1168+
 1169+ // Validate password
 1170+ $msg = false;
 1171+ $pwd = $this->getVar( '_AdminPassword' );
 1172+ if ( strval( $pwd ) === '' ) {
 1173+ $msg = 'config-admin-password-blank';
 1174+ } elseif ( $pwd === $cname ) {
 1175+ $msg = 'config-admin-password-same';
 1176+ } elseif ( $pwd !== $this->getVar( '_AdminPassword2' ) ) {
 1177+ $msg = 'config-admin-password-mismatch';
 1178+ }
 1179+ if ( $msg !== false ) {
 1180+ $this->parent->showError( $msg );
 1181+ $this->setVar( '_AdminPassword', '' );
 1182+ $this->setVar( '_AdminPassword2', '' );
 1183+ $retVal = false;
 1184+ }
 1185+ return $retVal;
 1186+ }
 1187+
7911188 }
792 -class WebInstaller_License extends WebInstallerPage {
 1189+class WebInstaller_Options extends WebInstallerPage {
 1190+ function execute() {
 1191+ if ( $this->getVar( '_SkipOptional' ) == 'skip' ) {
 1192+ return 'skip';
 1193+ }
 1194+ if ( $this->parent->request->wasPosted() ) {
 1195+ if ( $this->submit() ) {
 1196+ return 'continue';
 1197+ }
 1198+ }
 1199+
 1200+ $licenseJs = 'showControlArray("config__LicenseCode_cc-choose", ["config-cc-wrapper"]);';
 1201+ $emailJs = 'enableControlArray("config_wgEnableEmail", ["config_wgPasswordSender"]);';
 1202+ $uploadJs = 'enableControlArray("config_wgEnableUploads", ["config_wgDeletedDirectory"]);';
 1203+
 1204+ $this->startForm();
 1205+ $this->parent->output->addHTML(
 1206+ $this->parent->getRadioSet( array(
 1207+ 'var' => '_RightsProfile',
 1208+ 'label' => 'config-profile',
 1209+ 'itemLabelPrefix' => 'config-profile-',
 1210+ 'values' => array_keys( $this->parent->rightsProfiles ),
 1211+ ) ) .
 1212+ $this->parent->getHelpBox( 'config-profile-help' ) .
 1213+ $this->parent->getRadioSet( array(
 1214+ 'var' => '_LicenseCode',
 1215+ 'label' => 'config-license',
 1216+ 'itemLabelPrefix' => 'config-license-',
 1217+ 'values' => array_keys( $this->parent->licenses ),
 1218+ 'commonAttribs' => array( 'onclick' => $licenseJs )
 1219+ ) ) .
 1220+ $this->getCCChooser() .
 1221+ $this->parent->getHelpBox( 'config-license-help' ) .
 1222+ $this->parent->getFieldsetStart( 'config-email-settings' ) .
 1223+ $this->parent->getCheckBox( array(
 1224+ 'var' => 'wgEnableEmail',
 1225+ 'label' => 'config-enable-email',
 1226+ 'attribs' => array( 'onclick' => $emailJs ),
 1227+ ) ) .
 1228+ $this->parent->getHelpBox( 'config-enable-email-help' ) .
 1229+ $this->parent->getTextBox( array(
 1230+ 'var' => 'wgPasswordSender',
 1231+ 'label' => 'config-email-sender'
 1232+ ) ) .
 1233+ $this->parent->getHelpBox( 'config-email-sender-help' ) .
 1234+ $this->parent->getFieldsetEnd() .
 1235+ $this->parent->getFieldsetStart( 'config-upload-settings' ) .
 1236+ $this->parent->getCheckBox( array(
 1237+ 'var' => 'wgEnableUploads',
 1238+ 'label' => 'config-upload-enable',
 1239+ 'attribs' => array( 'onclick' => $uploadJs ),
 1240+ ) ) .
 1241+ $this->parent->getHelpBox( 'config-upload-help' ) .
 1242+ $this->parent->getTextBox( array(
 1243+ 'var' => 'wgDeletedDirectory',
 1244+ 'label' => 'config-upload-deleted',
 1245+ ) ) .
 1246+ $this->parent->getHelpBox( 'config-upload-deleted-help' ) .
 1247+ $this->parent->getTextBox( array(
 1248+ 'var' => 'wgLogo',
 1249+ 'label' => 'config-logo'
 1250+ ) ) .
 1251+ $this->parent->getHelpBox( 'config-logo-help' ) .
 1252+ $this->parent->getFieldsetEnd() .
 1253+ "<script type=\"text/javascript\">$licenseJs $emailJs $uploadJs</script>\n"
 1254+
 1255+ );
 1256+ $this->endForm();
 1257+ }
 1258+
 1259+ function getCCPartnerUrl() {
 1260+ global $wgServer;
 1261+ $exitUrl = $wgServer . $this->parent->getUrl( array(
 1262+ 'page' => 'Options',
 1263+ 'SubmitCC' => 'indeed',
 1264+ 'config__LicenseCode' => 'cc',
 1265+ 'config_wgRightsUrl' => '[license_url]',
 1266+ 'config_wgRightsText' => '[license_name]',
 1267+ 'config_wgRightsIcon' => '[license_button]',
 1268+ ) );
 1269+ $styleUrl = $wgServer . dirname( dirname( $this->parent->getUrl() ) ) .
 1270+ '/skins/common/config-cc.css';
 1271+ $iframeUrl = 'http://creativecommons.org/license/?' .
 1272+ wfArrayToCGI( array(
 1273+ 'partner' => 'MediaWiki',
 1274+ 'exit_url' => $exitUrl,
 1275+ 'lang' => $this->getVar( '_UserLang' ),
 1276+ 'stylesheet' => $styleUrl,
 1277+ ) );
 1278+ return $iframeUrl;
 1279+ }
 1280+
 1281+ function getCCChooser() {
 1282+ $iframeAttribs = array(
 1283+ 'class' => 'config-cc-iframe',
 1284+ 'name' => 'config-cc-iframe',
 1285+ 'id' => 'config-cc-iframe',
 1286+ 'frameborder' => 0,
 1287+ 'width' => '100%',
 1288+ 'height' => '100%',
 1289+ );
 1290+ if ( $this->getVar( '_CCDone' ) ) {
 1291+ $iframeAttribs['src'] = $this->parent->getUrl( array( 'ShowCC' => 'yes' ) );
 1292+ } else {
 1293+ $iframeAttribs['src'] = $this->getCCPartnerUrl();
 1294+ }
 1295+
 1296+ return
 1297+ "<div class=\"config-cc-wrapper\" id=\"config-cc-wrapper\">\n" .
 1298+ Xml::element( 'iframe', $iframeAttribs, '', false /* not short */ ) .
 1299+ "</div>\n";
 1300+ }
 1301+
 1302+ function getCCDoneBox() {
 1303+ $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';";
 1304+ // If you change this height, also change it in config.css
 1305+ $expandJs = str_replace( '$1', '54em', $js );
 1306+ $reduceJs = str_replace( '$1', '70px', $js );
 1307+ return
 1308+ '<p>'.
 1309+ Xml::element( 'img', array( 'src' => $this->getVar( 'wgRightsIcon' ) ) ) .
 1310+ '&nbsp;&nbsp;' .
 1311+ htmlspecialchars( $this->getVar( 'wgRightsText' ) ) .
 1312+ "</p>\n" .
 1313+ "<p style=\"text-align: center\">" .
 1314+ Xml::element( 'a',
 1315+ array(
 1316+ 'href' => $this->getCCPartnerUrl(),
 1317+ 'onclick' => $expandJs,
 1318+ ),
 1319+ wfMsg( 'config-cc-again' )
 1320+ ) .
 1321+ "</p>\n" .
 1322+ "<script type=\"text/javascript\">\n" .
 1323+ # Reduce the wrapper div height
 1324+ htmlspecialchars( $reduceJs ) .
 1325+ "\n" .
 1326+ "</script>\n";
 1327+ }
 1328+
 1329+
 1330+ function submitCC() {
 1331+ $newValues = $this->parent->setVarsFromRequest(
 1332+ array( 'wgRightsUrl', 'wgRightsText', 'wgRightsIcon' ) );
 1333+ if ( count( $newValues ) != 3 ) {
 1334+ $this->parent->showError( 'config-cc-error' );
 1335+ return;
 1336+ }
 1337+ $this->setVar( '_CCDone', true );
 1338+ $this->parent->output->addHTML( $this->getCCDoneBox() );
 1339+ }
 1340+
 1341+ function submit() {
 1342+ $this->parent->setVarsFromRequest( array( '_RightsProfile', '_LicenseCode',
 1343+ 'wgEnableEmail', 'wgPasswordSender', 'wgEnableUpload', 'wgLogo' ) );
 1344+
 1345+ if ( !in_array( $this->getVar( '_RightsProfile' ),
 1346+ array_keys( $this->parent->rightsProfiles ) ) )
 1347+ {
 1348+ reset( $this->parent->rightsProfiles );
 1349+ $this->setVar( '_RightsProfile', key( $this->parent->rightsProfiles ) );
 1350+ }
 1351+
 1352+ $code = $this->getVar( '_LicenseCode' );
 1353+ if ( $code == 'cc-choose' ) {
 1354+ if ( !$this->getVar( '_CCDone' ) ) {
 1355+ $this->parent->showError( 'config-cc-not-chosen' );
 1356+ return false;
 1357+ }
 1358+ } elseif ( in_array( $code, array_keys( $this->parent->licenses ) ) ) {
 1359+ $entry = $this->parent->licenses[$code];
 1360+ if ( isset( $entry['text'] ) ) {
 1361+ $this->setVar( 'wgRightsText', $entry['text'] );
 1362+ } else {
 1363+ $this->setVar( 'wgRightsText', wfMsg( 'config-license-' . $code ) );
 1364+ }
 1365+ $this->setVar( 'wgRightsUrl', $entry['url'] );
 1366+ $this->setVar( 'wgRightsIcon', $entry['icon'] );
 1367+ } else {
 1368+ $this->setVar( 'wgRightsText', '' );
 1369+ $this->setVar( 'wgRightsUrl', '' );
 1370+ $this->setVar( 'wgRightsIcon', '' );
 1371+ }
 1372+
 1373+ return true;
 1374+ }
7931375 }
794 -class WebInstaller_Email extends WebInstallerPage {
795 -}
7961376 class WebInstaller_Install extends WebInstallerPage {
7971377 }
7981378 class WebInstaller_Complete extends WebInstallerPage {
@@ -810,9 +1390,29 @@
8111391 }
8121392
8131393 $this->startForm();
814 - $s = $this->parent->getWarningBox( 'config-help-restart' );
 1394+ $s = $this->parent->getWarningBox( wfMsgNoTrans( 'config-help-restart' ) );
8151395 $this->parent->output->addHTML( $s );
8161396 $this->endForm( 'restart' );
8171397 }
8181398 }
8191399
 1400+abstract class WebInstaller_Document extends WebInstallerPage {
 1401+ abstract function getFileName();
 1402+
 1403+ function execute() {
 1404+ $text = file_get_contents( dirname( __FILE__ ) . '/../../' . $this->getFileName() );
 1405+ $this->parent->output->addWikiText( $text );
 1406+ $this->startForm();
 1407+ $this->endForm( false );
 1408+ }
 1409+}
 1410+
 1411+class WebInstaller_Readme extends WebInstaller_Document {
 1412+ function getFileName() { return 'README'; }
 1413+}
 1414+class WebInstaller_ReleaseNotes extends WebInstaller_Document {
 1415+ function getFileName() { return 'RELEASE-NOTES'; }
 1416+}
 1417+class WebInstaller_Copying extends WebInstaller_Document {
 1418+ function getFileName() { return 'COPYING'; }
 1419+}
Index: branches/new-installer/phase3/includes/installer/WebInstallerOutput.php
@@ -14,6 +14,7 @@
1515 var $headerDone = false;
1616 var $redirectTarget;
1717 var $debug = true;
 18+ var $useShortHeader = false;
1819
1920 function __construct( $parent ) {
2021 $this->parent = $parent;
@@ -41,6 +42,10 @@
4243 $this->outputFooter();
4344 }
4445
 46+ function useShortHeader( $use = true ) {
 47+ $this->useShortHeader = $use;
 48+ }
 49+
4550 function flush() {
4651 if ( !$this->headerDone ) {
4752 $this->outputHeader();
@@ -63,202 +68,34 @@
6469 return;
6570 }
6671
67 -
 72+ if ( $this->useShortHeader ) {
 73+ $this->outputShortHeader();
 74+ return;
 75+ }
 76+
6877 ?>
6978 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
7079 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
7180 <head>
 81+ <meta name="robots" content="noindex, nofollow">
7282 <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
7383 <title>MediaWiki <?php echo( htmlspecialchars( $wgVersion ) ); ?> Installation</title>
74 - <style type="text/css">
75 -
76 - @import "../skins/monobook/main.css";
77 -
78 - .env-check {
79 - font-size: 90%;
80 - margin: 1em 0 1em 2.5em;
81 - }
82 -
83 - .config-section {
84 - margin-top: 2em;
85 - }
86 -
87 - .config-label {
88 - clear: left;
89 - font-weight: bold;
90 - width: 10em;
91 - float: left;
92 - text-align: right;
93 - padding-right: 1em;
94 - padding-top: .2em;
95 - }
96 -
97 - .config-input {
98 - clear: left;
99 - zoom: 100%; /* IE hack */
100 - }
101 -
102 - .config-page-wrapper {
103 - padding: 0.5em;
104 - }
105 -
106 - .config-page-list {
107 - float: right;
108 - width: 12em;
109 - border: 1px solid #aaa;
110 - padding: 0.5em;
111 - margin: 0.5em;
112 - }
113 -
114 - .config-page {
115 - padding: 0.5em 2em 0.5em 2em;
116 - /* 15em right margin to leave space for 12em page list */
117 - margin: 0.5em 15em 0.5em 0.5em;
118 - border: 1px solid #aaa;
119 - }
120 -
121 - .config-submit {
122 - clear: left;
123 - text-align: center;
124 - padding: 1em;
125 - }
126 -
127 - .config-submit input {
128 - margin-left: 0.5em;
129 - margin-right: 0.5em;
130 - }
131 -
132 - .config-page-disabled {
133 - color: #aaa;
134 - }
135 -
136 - .config-info-left {
137 - margin: 0.5em;
138 - float: left;
139 - width: 35px;
140 - }
141 -
142 - .config-info-right {
143 - margin: 0.5em;
144 - float: left;
145 - width: 30em;
146 - }
147 -
148 - .config-page-current {
149 - font-weight: bold;
150 - }
151 -
152 - .config-desc {
153 - clear: left;
154 - margin: 0 0 2em 12em;
155 - padding-top: 1em;
156 - font-size: 85%;
157 - }
158 -
159 - .config-message {
160 - display: list-item;
161 - line-height: 1.5em;
162 - list-style-image: url(../skins/common/images/bullet.gif);
163 - list-style-type: square;
164 - }
165 -
166 - .config-input-text {
167 - width: 20em;
168 - margin-right: 1em;
169 - }
170 -
171 - .config-input-check {
172 - margin-left: 10em;
173 - }
174 -
175 - .error {
176 - color: red;
177 - background-color: #fff;
178 - font-weight: bold;
179 - left: 1em;
180 - font-size: 100%;
181 - }
182 -
183 - .config-error-top {
184 - background-color: #FFF0F0;
185 - border: 2px solid red;
186 - font-size: 110%;
187 - font-weight: bold;
188 - padding: 1em 1.5em;
189 - margin: 2em 0 1em;
190 - }
191 -
192 - .config-settings-block {
193 - list-style-type: none;
194 - list-style-image: none;
195 - float: left;
196 - margin: 0;
197 - padding: 0;
198 - }
199 -
200 - .btn-install {
201 - font-weight: bold;
202 - font-size: 110%;
203 - padding: .2em .3em;
204 - }
205 -
206 - .license {
207 - clear: both;
208 - font-size: 85%;
209 - padding-top: 3em;
210 - }
211 -
212 - .success-message {
213 - font-weight: bold;
214 - font-size: 110%;
215 - color: green;
216 - }
217 - .success-box {
218 - font-size: 130%;
219 - }
220 -
221 - </style>
222 - <script type="text/javascript">
223 - <!--
224 -<?php
225 - echo "var dbTypes = " . Xml::encodeJsVar( $dbTypes ) . "\n";
226 -?>
227 - function hideAllDBs() {
228 - for ( var i = 0; i < dbTypes.length; i++ ) {
229 - elt = document.getElementById( 'DB_wrapper_' + dbTypes[i] );
230 - if ( elt ) elt.style.display = 'none';
231 - }
232 - }
233 - function showDBArea(type) {
234 - hideAllDBs();
235 - var div = document.getElementById('DB_wrapper_' + type);
236 - if (div) div.style.display = 'block';
237 - }
238 - function resetDBArea() {
239 - for ( var i = 0; i < dbTypes.length; i++ ) {
240 - input = document.getElementById('DBType_' + dbTypes[i]);
241 - if ( input && input.checked ) {
242 - showDBArea( dbTypes[i] );
243 - return;
244 - }
245 - }
246 - }
247 - function disableControlArray( sourceID, targetIDs ) {
248 - var source = document.getElementById( sourceID );
249 - var disabled = source.checked ? '1' : '';
250 - if ( !source ) {
251 - return;
252 - }
253 - for ( var i = 0; i < targetIDs.length; i++ ) {
254 - var elt = document.getElementById( targetIDs[i] );
255 - if ( elt ) elt.disabled = disabled;
256 - }
257 - }
 84+ <link rel="stylesheet" type="text/css" href="../skins/monobook/main.css"/>
 85+ <link rel="stylesheet" type="text/css" href="../skins/common/config.css"/>
 86+ <script type="text/javascript"><!--
 87+<?php echo "var dbTypes = " . Xml::encodeJsVar( $dbTypes ) . ";\n"; ?>
25888 // -->
25989 </script>
 90+ <script type="text/javascript" src="../skins/common/config.js"></script>
26091 </head>
26192
26293 <body>
 94+<noscript>
 95+<style>
 96+.config-help-message { display: block; }
 97+.config-show-help { display: none; }
 98+</style>
 99+</noscript>
263100 <div id="globalWrapper">
264101 <div id="column-content">
265102 <div id="content">
@@ -269,25 +106,14 @@
270107 }
271108
272109 function outputFooter() {
 110+ if ( $this->useShortHeader ) {
273111 ?>
274 - <div class="license">
275 - <hr/>
276 - <p>This program is free software; you can redistribute it and/or modify
277 - it under the terms of the GNU General Public License as published by
278 - the Free Software Foundation; either version 2 of the License, or
279 - (at your option) any later version.</p>
 112+</body></html>
 113+<?php
 114+ return;
 115+ }
 116+?>
280117
281 - <p>This program is distributed in the hope that it will be useful,
282 - but WITHOUT ANY WARRANTY; without even the implied warranty of
283 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284 - GNU General Public License for more details.</p>
285 -
286 - <p>You should have received <a href="../COPYING">a copy of the GNU General Public License</a>
287 - along with this program; if not, write to the Free Software
288 - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
289 - or <a href="http://www.gnu.org/copyleft/gpl.html">read it online</a></p>
290 - </div>
291 -
292118 </div></div></div>
293119
294120
@@ -299,18 +125,9 @@
300126 </div>
301127 <script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script>
302128 <div class='portlet'><div class='pBody'>
303 - <ul>
304 - <li><strong><a href="http://www.mediawiki.org/">MediaWiki home</a></strong></li>
305 - <li><a href="../README">Readme</a></li>
306 - <li><a href="../RELEASE-NOTES">Release notes</a></li>
307 - <li><a href="../docs/">Documentation</a></li>
308 - <li><a href="http://www.mediawiki.org/wiki/Help:Contents">User's Guide</a></li>
309 - <li><a href="http://www.mediawiki.org/wiki/Manual:Contents">Administrator's Guide</a></li>
310 - <li><a href="http://www.mediawiki.org/wiki/Manual:FAQ">FAQ</a></li>
311 - </ul>
312 - <p style="font-size:90%;margin-top:1em">MediaWiki is Copyright © 2001-2008 by Magnus Manske, Brion Vibber,
313 - Lee Daniel Crocker, Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason, Niklas Laxström,
314 - Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor, Aaron Schulz and others.</p>
 129+<?php
 130+ echo $this->parent->parse( wfMsgNoTrans( 'config-sidebar' ), true );
 131+?>
315132 </div></div>
316133 </div>
317134
@@ -320,4 +137,21 @@
321138 </html>
322139 <?php
323140 }
 141+
 142+ function outputShortHeader() {
 143+?>
 144+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 145+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
 146+<head>
 147+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
 148+ <meta name="robots" content="noindex, nofollow">
 149+ <title>MediaWiki <?php echo( htmlspecialchars( $wgVersion ) ); ?> Installation</title>
 150+ <link rel="stylesheet" type="text/css" href="../skins/monobook/main.css"/>
 151+ <link rel="stylesheet" type="text/css" href="../skins/common/config.css"/>
 152+ <script type="text/javascript" src="../skins/common/config.js"></script>
 153+</head>
 154+
 155+<body style="background-image: none">
 156+<?php
 157+ }
324158 }
Index: branches/new-installer/phase3/includes/installer/Installer.php
@@ -22,15 +22,16 @@
2323 'wgRightsUrl',
2424 'wgMainCacheType',
2525 'wgEnableEmail',
26 - 'wgEnableUserEmail',
27 - 'wgEnotifUserTalk',
28 - 'wgEnotifWatchlist',
2926 'wgDBtype',
3027 'wgDiff3',
3128 'wgImageMagickConvertCommand',
3229 'IP',
3330 'wgScriptPath',
3431 'wgScriptExtension',
 32+ 'wgMetaNamespace',
 33+ 'wgDeletedDirectory',
 34+ 'wgEnableUploads',
 35+ 'wgLogo',
3536 );
3637
3738 /**
@@ -40,12 +41,27 @@
4142 * @protected
4243 */
4344 var $internalDefaults = array(
 45+ '_UserLang' => 'en',
4446 '_Environment' => false,
4547 '_CompiledDBs' => array(),
4648 '_SafeMode' => false,
4749 '_RaiseMemory' => false,
4850 '_UpgradeDone' => false,
4951 '_Caches' => array(),
 52+ '_InstallUser' => 'root',
 53+ '_InstallPassword' => '',
 54+ '_SameAccount' => true,
 55+ '_CreateDBAccount' => false,
 56+ '_NamespaceType' => 'site-name',
 57+ '_AdminName' => '',
 58+ '_AdminPassword' => '',
 59+ '_AdminPassword2' => '',
 60+ '_AdminEmail' => '',
 61+ '_Subscribe' => false,
 62+ '_SkipOptional' => 'continue',
 63+ '_RightsProfile' => 'wiki',
 64+ '_LicenseCode' => 'none',
 65+ '_CCDone' => false,
5066 );
5167
5268 /**
@@ -63,6 +79,11 @@
6480 );
6581
6682 /**
 83+ * Minimum memory size in MB
 84+ */
 85+ var $minMemory = 50;
 86+
 87+ /**
6788 * Cached DB installer instances, access using getDBInstaller()
6889 * @private
6990 */
@@ -104,6 +125,57 @@
105126 );
106127
107128 /**
 129+ * User rights profiles
 130+ */
 131+ var $rightsProfiles = array(
 132+ 'wiki' => array(),
 133+ 'no-anon' => array(
 134+ '*' => array( 'edit' => false )
 135+ ),
 136+ 'fishbowl' => array(
 137+ '*' => array(
 138+ 'createaccount' => false,
 139+ 'edit' => false,
 140+ ),
 141+ ),
 142+ 'private' => array(
 143+ '*' => array(
 144+ 'createaccount' => false,
 145+ 'edit' => false,
 146+ 'read' => false,
 147+ ),
 148+ ),
 149+ );
 150+
 151+ /**
 152+ * License types
 153+ */
 154+ var $licenses = array(
 155+ 'none' => array(
 156+ 'url' => '',
 157+ 'icon' => '',
 158+ 'text' => ''
 159+ ),
 160+ 'pd' => array(
 161+ 'url' => 'http://creativecommons.org/licenses/publicdomain/',
 162+ 'icon' => '${wgScriptPath}/skins/common/images/public-domain.png',
 163+ ),
 164+ 'gfdl-old' => array(
 165+ 'url' => 'http://www.gnu.org/licenses/old-licenses/fdl-1.2.html',
 166+ 'icon' => '${wgScriptPath}/skins/common/images/gnu-fdl.png',
 167+ ),
 168+ 'gfdl-current' => array(
 169+ 'url' => 'http://www.gnu.org/copyleft/fdl.html',
 170+ 'icon' => '${wgScriptPath}/skins/common/images/gnu-fdl.png',
 171+ ),
 172+ 'cc-choose' => array(
 173+ // details will be filled in by the selector
 174+ 'url' => '',
 175+ 'icon' => '',
 176+ 'text' => '',
 177+ ),
 178+ );
 179+ /**
108180 * Cached Title and ParserOptions used by parse()
109181 * @private
110182 */
@@ -343,11 +415,12 @@
344416 if( preg_match( '/^([0-9]+)[Mm]$/', trim( $limit ), $m ) ) {
345417 $n = intval( $m[1] * (1024*1024) );
346418 }
347 - if( $n < 20*1024*1024 ) {
348 - if( false === ini_set( "memory_limit", "20M" ) ) {
 419+ if( $n < $this->minMemorySize*1024*1024 ) {
 420+ $newLimit = "{$this->minMemorySize}M";
 421+ if( false === ini_set( "memory_limit", $newLimit ) ) {
349422 $this->showMessage( 'config-memory-bad', $limit );
350423 } else {
351 - $this->showMessage( 'config-memory-raised', $limit );
 424+ $this->showMessage( 'config-memory-raised', $limit, $newLimit );
352425 $this->setVar( '_RaiseMemory', true );
353426 }
354427 } else {
@@ -507,19 +580,36 @@
508581 * @param string $text
509582 * @return string
510583 */
511 - function parse( $text ) {
 584+ function parse( $text, $lineStart = false ) {
512585 global $wgParser;
513586 try {
514 - $out = $wgParser->parse( $text, $this->parserTitle, $this->parserOptions, false );
 587+ $out = $wgParser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart );
515588 $html = $out->getText();
516589 } catch ( InstallerDBAccessError $e ) {
517590 $html = '<!--DB access attempted during parse--> ' . htmlspecialchars( $text );
518 - if ( $this->debug ) {
 591+ if ( !empty( $this->debug ) ) {
519592 $html .= "<!--\n" . $e->getTraceAsString() . "\n-->";
520593 }
521594 }
522595 return $html;
523596 }
 597+
 598+ /**
 599+ * Extension tag hook for a documentation link
 600+ */
 601+ function docLink( $linkText, $attribs, $parser ) {
 602+ $url = $this->getDocUrl( $attribs['href'] );
 603+ return '<a href="' . htmlspecialchars( $url ) . '">' .
 604+ htmlspecialchars( $linkText ) .
 605+ '</a>';
 606+ }
 607+
 608+ /**
 609+ * Overridden by WebInstaller to provide lastPage parameters
 610+ */
 611+ protected function getDocUrl( $page ) {
 612+ return "{$_SERVER['PHP_SELF']}?page=" . urlencode( $attribs['href'] );
 613+ }
524614 }
525615
526616 /**
Index: branches/new-installer/phase3/includes/installer/SqliteInstaller.php
@@ -28,15 +28,15 @@
2929
3030 function getConnectForm() {
3131 return
32 - $this->getLabelledTextBox( 'wgSQLiteDataDir', 'config-sqlite-dir' ) .
 32+ $this->getTextBox( 'wgSQLiteDataDir', 'config-sqlite-dir' ) .
3333 $this->parent->getHelpBox( 'config-sqlite-dir-help' ) .
34 - $this->getLabelledTextBox( 'wgDBname', 'config-db-name' ) .
 34+ $this->getTextBox( 'wgDBname', 'config-db-name' ) .
3535 $this->parent->getHelpBox( 'config-sqlite-name-help' );
3636 }
3737
3838 function submitConnectForm() {
3939 global $wgSQLiteDataDirMode, $wgSQLiteDataDir;
40 - $newValues = $this->setVarsFromRequest();
 40+ $newValues = $this->setVarsFromRequest( array( 'wgSQLiteDataDir', 'wgDBname' ) );
4141 $dir = $newValues['wgSQLiteDataDir'];
4242 if ( !is_dir( $dir ) ) {
4343 if ( !is_writable( dirname( $dir ) ) ) {
@@ -55,17 +55,46 @@
5656 return Status::newFatal( 'config-sqlite-unwritable', $dir );
5757 }
5858 return Status::newGood();
59 - /* -- during install:
 59+ }
 60+
 61+ function getConnection() {
6062 $status = Status::newGood();
 63+ $dir = $this->getVar( 'wgSQLiteDataDir' );
 64+ $dbName = $this->getVar( 'wgDBname' );
 65+
6166 try {
6267 # FIXME: need more sensible constructor parameters, e.g. single associative array
6368 # Setting globals kind of sucks
6469 $wgSQLiteDataDir = $dir;
65 - $this->conn = new DatabaseSqlite( false, false, false, $newValues['wgDBname'] );
 70+ $this->conn = new DatabaseSqlite( false, false, false, $dbName );
 71+ return $this->conn;
6672 } catch ( DBConnectionError $e ) {
6773 $status->fatal( 'config-sqlite-connection-error', $e->getMessage() );
6874 }
6975 return $status;
70 - */
7176 }
 77+
 78+ function needsUpgrade() {
 79+ $dir = $this->getVar( 'wgSQLiteDataDir' );
 80+ $dbName = $this->getVar( 'wgDBname' );
 81+ // Don't create the data file yet
 82+ if ( !file_exists( "$dir/$dbName.sqlite" ) ) {
 83+ return false;
 84+ }
 85+
 86+ // If the data file exists, look inside it
 87+ return parent::needsUpgrade();
 88+ }
 89+
 90+ function getSettingsForm() {
 91+ return false;
 92+ }
 93+
 94+ function submitSettingsForm() {
 95+ return Status::newGood();
 96+ }
 97+
 98+ function install() {
 99+ echo "TODO";
 100+ }
72101 }
Index: branches/new-installer/phase3/includes/installer/MysqlInstaller.php
@@ -12,13 +12,22 @@
1313 );
1414
1515 var $internalDefaults = array(
16 - '_MysqlInstallUser' => 'root',
17 - '_MysqlInstallPassword' => '',
18 - '_MysqlSameAccount' => true,
 16+ '_MysqlEngine' => 'InnoDB',
 17+ '_MysqlCharset' => 'binary',
1918 );
2019
 20+ var $supportedEngines = array( 'InnoDB', 'MyISAM' );
 21+
2122 var $minimumVersion = '4.0.14';
2223
 24+ var $webUserPrivs = array(
 25+ 'DELETE',
 26+ 'INSERT',
 27+ 'SELECT',
 28+ 'UPDATE',
 29+ 'CREATE TEMPORARY TABLES',
 30+ );
 31+
2332 var $conn;
2433
2534 function getName() {
@@ -43,26 +52,21 @@
4453
4554 function getConnectForm() {
4655 return
47 - $this->getLabelledTextBox( 'wgDBserver', 'config-db-host' ) .
 56+ $this->getTextBox( 'wgDBserver', 'config-db-host' ) .
4857 $this->parent->getHelpBox( 'config-db-host-help' ) .
4958 Xml::openElement( 'fieldset' ) .
5059 Xml::element( 'legend', array(), wfMsg( 'config-db-wiki-settings' ) ) .
51 - $this->getLabelledTextBox( 'wgDBname', 'config-db-name' ) .
 60+ $this->getTextBox( 'wgDBname', 'config-db-name' ) .
5261 $this->parent->getHelpBox( 'config-db-name-help' ) .
53 - $this->getLabelledTextBox( 'wgDBprefix', 'config-db-prefix' ) .
 62+ $this->getTextBox( 'wgDBprefix', 'config-db-prefix' ) .
5463 $this->parent->getHelpBox( 'config-db-prefix-help' ) .
5564 Xml::closeElement( 'fieldset' ) .
56 - Xml::openElement( 'fieldset' ) .
57 - Xml::element( 'legend', array(), wfMsg( 'config-db-install-account' ) ) .
58 - $this->getLabelledTextBox( '_MysqlInstallUser', 'config-db-username' ) .
59 - $this->getLabelledPasswordBox( '_MysqlInstallPassword', 'config-db-password' ) .
60 - $this->parent->getHelpBox( 'config-db-install-help' ) .
61 - Xml::closeElement( 'fieldset' );
 65+ $this->getInstallUserBox();
6266 }
6367
6468 function submitConnectForm() {
6569 // Get variables from the request
66 - $newValues = $this->setVarsFromRequest();
 70+ $newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBname', 'wgDBprefix' ) );
6771
6872 // Validate them
6973 $status = Status::newGood();
@@ -78,14 +82,21 @@
7983 return $status;
8084 }
8185
 86+ // Submit user box
 87+ $status = $this->submitInstallUserBox();
 88+ if ( !$status->isOK() ) {
 89+ return $status;
 90+ }
 91+
8292 // Try to connect
83 - $status = $this->attemptConnection();
 93+ $status = $this->getConnection();
8494 if ( !$status->isOK() ) {
8595 return $status;
8696 }
 97+ $conn = $status->value;
8798
8899 // Check version
89 - $version = $this->conn->getServerVersion();
 100+ $version = $conn->getServerVersion();
90101 if ( version_compare( $version, $this->minimumVersion ) < 0 ) {
91102 return Status::newFatal( 'config-mysql-old', $this->minimumVersion, $version );
92103 }
@@ -93,39 +104,33 @@
94105 return $status;
95106 }
96107
97 - function attemptConnection() {
 108+ function getConnection() {
98109 $status = Status::newGood();
99110 try {
100111 $this->conn = new Database(
101112 $this->getVar( 'wgDBserver' ),
102 - $this->getVar( '_MysqlInstallUser' ),
103 - $this->getVar( '_MysqlInstallPassword' ),
 113+ $this->getVar( '_InstallUser' ),
 114+ $this->getVar( '_InstallPassword' ),
104115 false,
105116 false,
106117 0,
107118 $this->getVar( 'wgDBprefix' )
108119 );
 120+ $status->value = $this->conn;
 121+ return $status;
109122 } catch ( DBConnectionError $e ) {
110123 $status->fatal( 'config-connection-error', $e->getMessage() );
111124 }
112125 return $status;
113126 }
114127
115 - function getConnection() {
116 - $status = $this->attemptConnection();
117 - if ( $status->isOK() ) {
118 - return $this->conn;
119 - } else {
120 - return $status;
121 - }
122 - }
123 -
124128 function doUpgrade() {
125 - $conn = $this->getConnection();
126 - if ( $conn instanceof Status ) {
127 - $this->parent->showStatusError( $conn );
 129+ $status = $this->getConnection();
 130+ if ( !$status->isOK() ) {
 131+ $this->parent->showStatusError( $status );
128132 return;
129133 }
 134+ $conn = $status->value;
130135
131136 # Determine existing default character set
132137 if ( $conn->tableExists( "revision" ) ) {
@@ -154,44 +159,218 @@
155160 }
156161 }
157162 }
158 -
159 - // TODO...
160 - return;
 163+
 164+ // TODO
 165+ }
161166
162 - # Create user if required
163 - if ( $conf->Root ) {
164 - $conn = $dbc->newFromParams( $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1 );
165 - if ( $conn->isOpen() ) {
166 - print "<li>DB user account ok</li>\n";
167 - $conn->close();
168 - } else {
169 - print "<li>Granting user permissions...";
170 - if( $mysqlOldClient && $mysqlNewAuth ) {
171 - print " <b class='error'>If the next step fails, see <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'>http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b>";
172 - }
173 - print "</li>\n";
174 - dbsource( "../maintenance/users.sql", $conn );
 167+ /**
 168+ * Get a list of storage engines that are available and supported
 169+ */
 170+ function getEngines() {
 171+ $engines = array( 'InnoDB', 'MyISAM' );
 172+ $status = $this->getConnection();
 173+ if ( !$status->isOK() ) {
 174+ return $engines;
 175+ }
 176+ $conn = $status->value;
 177+
 178+ $version = $conn->getServerVersion();
 179+ if ( version_compare( $version, "4.1.2", "<" ) ) {
 180+ // No SHOW ENGINES in this version
 181+ return $engines;
 182+ }
 183+
 184+ $engines = array();
 185+ $res = $conn->query( 'SHOW ENGINES' );
 186+ foreach ( $res as $row ) {
 187+ $engines[] = $row->Engine;
 188+ }
 189+ $engines = array_intersect( $this->supportedEngines, $engines );
 190+ return $engines;
 191+ }
 192+
 193+ /**
 194+ * Get a list of character sets that are available and supported
 195+ */
 196+ function getCharsets() {
 197+ $status = $this->getConnection();
 198+ $mysql5 = array( 'binary', 'utf-8' );
 199+ $mysql4 = array( 'mysql4' );
 200+ if ( !$status->isOK() ) {
 201+ return $mysql5;
 202+ }
 203+ if ( version_compare( $status->value->getServerVersion(), '4.1.0', '>=' ) ) {
 204+ return $mysql5;
 205+ }
 206+ return $mysql4;
 207+ }
 208+
 209+ /**
 210+ * Return true if the install user can create accounts
 211+ */
 212+ function canCreateAccounts() {
 213+ $status = $this->getConnection();
 214+ if ( !$status->isOK() ) {
 215+ return false;
 216+ }
 217+ $conn = $status->value;
 218+
 219+ // Check version, need INFORMATION_SCHEMA and CREATE USER
 220+ if ( version_compare( $conn->getServerVersion(), '5.0.2', '<' ) ) {
 221+ return false;
 222+ }
 223+
 224+ // Get current account name
 225+ $currentName = $conn->selectField( '', 'CURRENT_USER()', '', __METHOD__ );
 226+ $parts = explode( '@', $currentName );
 227+ if ( count( $parts ) != 2 ) {
 228+ return false;
 229+ }
 230+ $quotedUser = $conn->addQuotes( $parts[0] ) .
 231+ '@' . $conn->addQuotes( $parts[1] );
 232+
 233+ // The user needs to have INSERT on mysql.* to be able to CREATE USER
 234+ // The grantee will be double-quoted in this query, as required
 235+ $res = $conn->select( 'INFORMATION_SCHEMA.USER_PRIVILEGES', '*',
 236+ array( 'GRANTEE' => $quotedUser ), __METHOD__ );
 237+ $insertMysql = false;
 238+ $grantOptions = array_flip( $this->webUserPrivs );
 239+ foreach ( $res as $row ) {
 240+ if ( $row->PRIVILEGE_TYPE == 'INSERT' ) {
 241+ $insertMysql = true;
175242 }
 243+ if ( $row->IS_GRANTABLE ) {
 244+ unset( $grantOptions[$row->PRIVILEGE_TYPE] );
 245+ }
176246 }
 247+
 248+ // Check for DB-specific privs for mysql.*
 249+ if ( !$insertMysql ) {
 250+ $row = $conn->selectRow( 'INFORMATION_SCHEMA.SCHEMA_PRIVILEGES', '*',
 251+ array(
 252+ 'GRANTEE' => $quotedUser,
 253+ 'TABLE_SCHEMA' => 'mysql',
 254+ 'PRIVILEGE_TYPE' => 'INSERT',
 255+ ), __METHOD__ );
 256+ if ( $row ) {
 257+ $insertMysql = true;
 258+ }
 259+ }
 260+
 261+ if ( !$insertMysql ) {
 262+ return false;
 263+ }
 264+
 265+ // Check for DB-level grant options
 266+ $res = $conn->select( 'INFORMATION_SCHEMA.SCHEMA_PRIVILEGES', '*',
 267+ array(
 268+ 'GRANTEE' => $quotedUser,
 269+ 'IS_GRANTABLE' => 1,
 270+ ), __METHOD__ );
 271+ foreach ( $res as $row ) {
 272+ $regex = $conn->likeToRegex( $row->TABLE_SCHEMA );
 273+ if ( preg_match( $regex, $this->getVar( 'wgDBname' ) ) ) {
 274+ unset( $grantOptions[$row->PRIVILEGE_TYPE] );
 275+ }
 276+ }
 277+ if ( count( $grantOptions ) ) {
 278+ // Can't grant everything
 279+ return false;
 280+ }
 281+ return true;
177282 }
178283
179284 function getSettingsForm() {
180 - $installUser = $this->getVar( '_MysqlInstallUser' );
181 - $installPass = $this->parent->getFakePassword( $this->getVar( '_MysqlInstallPassword' ) );
182 - $js = 'disableControlArray( "mysql__MysqlSameAccount", ' .
183 - '["mysql_wgDBuser", "mysql_wgDBpassword"] )';
 285+ if ( $this->canCreateAccounts() ) {
 286+ $noCreateMsg = false;
 287+ } else {
 288+ $noCreateMsg = 'config-db-web-no-create-privs';
 289+ }
 290+ $s = $this->getWebUserBox( $noCreateMsg );
184291
185 - return
186 - Xml::openElement( 'fieldset' ) .
187 - Xml::element( 'legend', array(), wfMsg( 'config-db-web-account' ) ) .
188 - $this->getLabelledCheckBox(
189 - '_MysqlSameAccount', 'config-db-web-account-same', array( 'onclick' => $js )
190 - ) .
191 - "<br/>\n" .
192 - $this->getLabelledTextBox( 'wgDBuser', 'config-db-username' ) .
193 - $this->getLabelledPasswordBox( 'wgDBpassword', 'config-db-password' ) .
194 - $this->parent->getHelpBox( 'config-db-web-help' ) .
195 - Xml::closeElement( 'fieldset' ) .
196 - "<script type=\"text/javascript\">$js</script>";
 292+ // Do engine selector
 293+ $engines = $this->getEngines();
 294+ // If the current default engine is not supported, use an engine that is
 295+ if ( !in_array( $this->getVar( '_MysqlEngine' ), $engines ) ) {
 296+ $this->setVar( '_MysqlEngine', reset( $engines ) );
 297+ }
 298+ if ( count( $engines ) >= 2 ) {
 299+ $s .= $this->getRadioSet( array(
 300+ 'var' => '_MysqlEngine',
 301+ 'label' => 'config-mysql-engine',
 302+ 'itemLabelPrefix' => 'config-mysql-',
 303+ 'values' => $engines
 304+ ));
 305+ $s .= $this->parent->getHelpBox( 'config-mysql-engine-help' );
 306+ }
 307+
 308+ // If the current default charset is not supported, use a charset that is
 309+ $charsets = $this->getCharsets();
 310+ if ( !in_array( $this->getVar( '_MysqlCharset' ), $charsets ) ) {
 311+ $this->setVar( '_MysqlCharset', reset( $charsets ) );
 312+ }
 313+
 314+ // Do charset selector
 315+ if ( count( $charsets ) >= 2 ) {
 316+ $s .= $this->getRadioSet( array(
 317+ 'var' => '_MysqlCharset',
 318+ 'label' => 'config-mysql-charset',
 319+ 'itemLabelPrefix' => 'config-mysql-',
 320+ 'values' => $charsets
 321+ ));
 322+ $s .= $this->parent->getHelpBox( 'config-mysql-charset-help' );
 323+ }
 324+
 325+ return $s;
197326 }
 327+
 328+ function submitSettingsForm() {
 329+ $newValues = $this->setVarsFromRequest( array( '_MysqlEngine', '_MysqlCharset' ) );
 330+ $status = $this->submitWebUserBox();
 331+ if ( !$status->isOK() ) {
 332+ return $status;
 333+ }
 334+
 335+ // Validate the create checkbox
 336+ $canCreate = $this->canCreateAccounts();
 337+ if ( !$canCreate ) {
 338+ $this->setVar( '_CreateDBAccount', false );
 339+ $create = false;
 340+ } else {
 341+ $create = $this->getVar( '_CreateDBAccount' );
 342+ }
 343+
 344+ if ( !$create ) {
 345+ // Test the web account
 346+ try {
 347+ $webConn = new Database(
 348+ $this->getVar( 'wgDBserver' ),
 349+ $this->getVar( 'wgDBuser' ),
 350+ $this->getVar( 'wgDBpassword' ),
 351+ false,
 352+ false,
 353+ 0,
 354+ $this->getVar( 'wgDBprefix' )
 355+ );
 356+ } catch ( DBConnectionError $e ) {
 357+ return Status::newFatal( 'config-connection-error', $e->getMessage() );
 358+ }
 359+ }
 360+
 361+ // Validate engines and charsets
 362+ // This is done pre-submit already so it's just for security
 363+ $engines = $this->getEngines();
 364+ if ( !in_array( $this->getVar( '_MysqlEngine' ), $engines ) ) {
 365+ $this->setVar( '_MysqlEngine', reset( $engines ) );
 366+ }
 367+ $charsets = $this->getCharsets();
 368+ if ( !in_array( $this->getVar( '_MysqlCharset' ), $charsets ) ) {
 369+ $this->setVar( '_MysqlCharset', reset( $charsets ) );
 370+ }
 371+ return Status::newGood();
 372+ }
 373+
 374+ function install() {
 375+ echo "TODO";
 376+ }
198377 }
Index: branches/new-installer/phase3/includes/installer/PostgresInstaller.php
@@ -39,28 +39,24 @@
4040
4141 function getConnectForm() {
4242 return
43 - $this->getLabelledTextBox( 'wgDBserver', 'config-db-host' ) .
 43+ $this->getTextBox( 'wgDBserver', 'config-db-host' ) .
4444 $this->parent->getHelpBox( 'config-db-host-help' ) .
45 - $this->getLabelledTextBox( 'wgDBport', 'config-db-port' ) .
 45+ $this->getTextBox( 'wgDBport', 'config-db-port' ) .
4646 Xml::openElement( 'fieldset' ) .
4747 Xml::element( 'legend', array(), wfMsg( 'config-db-wiki-settings' ) ) .
48 - $this->getLabelledTextBox( 'wgDBname', 'config-db-name' ) .
 48+ $this->getTextBox( 'wgDBname', 'config-db-name' ) .
4949 $this->parent->getHelpBox( 'config-db-name-help' ) .
50 - $this->getLabelledTextBox( 'wgDBmwschema', 'config-db-schema' ) .
51 - $this->getLabelledTextBox( 'wgDBts2schema', 'config-db-ts2-schema' ) .
 50+ $this->getTextBox( 'wgDBmwschema', 'config-db-schema' ) .
 51+ $this->getTextBox( 'wgDBts2schema', 'config-db-ts2-schema' ) .
5252 $this->parent->getHelpBox( 'config-db-schema-help' ) .
5353 Xml::closeElement( 'fieldset' ) .
54 - Xml::openElement( 'fieldset' ) .
55 - Xml::element( 'legend', array(), wfMsg( 'config-db-install-account' ) ) .
56 - $this->getLabelledTextBox( '_PostgresInstallUser', 'config-db-username' ) .
57 - $this->getLabelledPasswordBox( '_PostgresInstallPassword', 'config-db-password' ) .
58 - $this->parent->getHelpBox( 'config-db-install-help' ) .
59 - Xml::closeElement( 'fieldset' );
 54+ $this->getInstallUserBox();
6055 }
6156
6257 function submitConnectForm() {
6358 // Get variables from the request
64 - $newValues = $this->setVarsFromRequest();
 59+ $newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBport',
 60+ 'wgDBname', 'wgDBmwschema', 'wgDBts2schema' ) );
6561
6662 // Validate them
6763 $status = Status::newGood();
@@ -107,4 +103,24 @@
108104 return $status;
109105 }
110106
 107+ function getConnection() {
 108+ $status = $this->attemptConnection();
 109+ if ( $status->isOK() ) {
 110+ return $this->conn;
 111+ } else {
 112+ return $status;
 113+ }
 114+ }
 115+
 116+ function getSettingsForm() {
 117+ return false;
 118+ }
 119+
 120+ function submitSettingsForm() {
 121+ return Status::newGood();
 122+ }
 123+
 124+ function install() {
 125+ echo "TODO";
 126+ }
111127 }
Index: branches/new-installer/phase3/includes/installer/InstallerDBType.php
@@ -7,6 +7,70 @@
88 /** The Installer object */
99 var $parent;
1010
 11+ /**
 12+ * Return the internal name, e.g. 'mysql', or 'sqlite'
 13+ */
 14+ abstract function getName();
 15+
 16+ /**
 17+ * @return true if the client library is compiled in
 18+ */
 19+ abstract function isCompiled();
 20+
 21+ /**
 22+ * Get an array of MW configuration globals that will be configured by this class.
 23+ */
 24+ abstract function getGlobalNames();
 25+
 26+ /**
 27+ * Get HTML for a web form that configures this database. Configuration
 28+ * at this time should be the minimum needed to connect and test
 29+ * whether install or upgrade is required.
 30+ *
 31+ * If this is called, $this->parent can be assumed to be a WebInstaller
 32+ */
 33+ abstract function getConnectForm();
 34+
 35+ /**
 36+ * Set variables based on the request array, assuming it was submitted
 37+ * via the form returned by getConnectForm(). Validate the connection
 38+ * settings by attempting to connect with them.
 39+ *
 40+ * If this is called, $this->parent can be assumed to be a WebInstaller
 41+ *
 42+ * @return Status
 43+ */
 44+ abstract function submitConnectForm();
 45+
 46+ /**
 47+ * Get HTML for a web form that retrieves settings used for installation.
 48+ * $this->parent can be assumed to be a WebInstaller.
 49+ * If the DB type has no settings beyond those already configured with
 50+ * getConnectForm(), this should return false.
 51+ */
 52+ abstract function getSettingsForm();
 53+
 54+ /**
 55+ * Set variables based on the request array, assuming it was submitted via
 56+ * the form return by getSettingsForm().
 57+ * @return Status
 58+ */
 59+ abstract function submitSettingsForm();
 60+
 61+ /**
 62+ * Connect to the database using the administrative user/password currently
 63+ * defined in the session. On success, return the connection, on failure,
 64+ * return a Status object.
 65+ *
 66+ * This may be called multiple times, so the result should be cached.
 67+ */
 68+ abstract function getConnection();
 69+
 70+ /**
 71+ * Create a database and MediaWiki tables with the configured settings
 72+ */
 73+ abstract function install();
 74+
1175 /**
1276 * Construct and initialise parent.
1377 * This is typically only called from Installer::getDBInstaller()
@@ -28,26 +92,11 @@
2993 }
3094
3195 /**
32 - * Return the internal name, e.g. 'mysql', or 'sqlite'
33 - */
34 - abstract function getName();
35 -
36 - /**
3796 * Get the internationalised name for this DBMS
3897 */
3998 function getReadableName() {
4099 return wfMsg( 'config-type-' . $this->getName() );
41100 }
42 -
43 - /**
44 - * @return true if the client library is compiled in
45 - */
46 - abstract function isCompiled();
47 -
48 - /**
49 - * Get an array of MW configuration globals that will be configured by this class.
50 - */
51 - abstract function getGlobalNames();
52101
53102 /**
54103 * Get a name=>value map of MW configuration globals that overrides
@@ -65,19 +114,6 @@
66115 }
67116
68117 /**
69 - * Get HTML for a web form that configures this database
70 - * If this is called, $this->parent can be assumed to be a WebInstaller
71 - */
72 - abstract function getConnectForm();
73 -
74 - /**
75 - * Set variables based on the request array, assuming it was submitted
76 - * via the form returned by getConnectForm()
77 - * If this is called, $this->parent can be assumed to be a WebInstaller
78 - */
79 - abstract function submitConnectForm();
80 -
81 - /**
82118 * Get a variable, taking local defaults into account
83119 */
84120 function getVar( $var, $default = null ) {
@@ -92,72 +128,170 @@
93129 }
94130
95131 /**
96 - * Convenience function for a labelled text box to configure a variable
 132+ * Convenience alias for $this->parent->setVar()
97133 */
98 - function getLabelledTextBox( $var, $label ) {
 134+ function setVar( $name, $value ) {
 135+ $this->parent->setVar( $name, $value );
 136+ }
 137+
 138+ /**
 139+ * Get a labelled text box to configure a local variable
 140+ */
 141+ function getTextBox( $var, $label, $attribs = array() ) {
99142 $name = $this->getName() . '_' . $var;
100143 $value = $this->getVar( $var );
101 - return
102 - "<div class=\"config-input\">\n" .
103 - $this->parent->getLabel( $label, $name ) .
104 - $this->parent->getTextBox( $name, $value ) .
105 - "</div>\n";
 144+ return $this->parent->getTextBox( array(
 145+ 'var' => $var,
 146+ 'label' => $label,
 147+ 'attribs' => $attribs,
 148+ 'controlName' => $name,
 149+ 'value' => $value
 150+ ) );
106151 }
107152
108153 /**
109 - * Convenience function for a labelled password box.
 154+ * Get a labelled password box to configure a local variable
110155 * Implements password hiding
111156 */
112 - function getLabelledPasswordBox( $var, $label ) {
 157+ function getPasswordBox( $var, $label, $attribs = array() ) {
113158 $name = $this->getName() . '_' . $var;
114 - $realPassword = $this->getVar( $var );
115 - if ( strlen( $var ) ) {
116 - $fakeValue = $this->parent->getFakePassword( $realPassword );
117 - } else {
118 - $fakeValue = '';
119 - }
120 - return
121 - "<div class=\"config-input\">\n" .
122 - $this->parent->getLabel( $label, $name ) .
123 - $this->parent->getTextBox( $name, $fakeValue, 'password' ) .
124 - "</div>\n";
 159+ $value = $this->getVar( $var );
 160+ return $this->parent->getPasswordBox( array(
 161+ 'var' => $var,
 162+ 'label' => $label,
 163+ 'attribs' => $attribs,
 164+ 'controlName' => $name,
 165+ 'value' => $value
 166+ ) );
125167 }
126168
127169 /**
128 - * Convenience function for a labelled checkbox
 170+ * Get a labelled checkbox to configure a local boolean variable
129171 */
130 - function getLabelledCheckBox( $var, $label, $attribs = array() ) {
 172+ function getCheckBox( $var, $label, $attribs = array() ) {
131173 $name = $this->getName() . '_' . $var;
132174 $value = $this->getVar( $var );
133 - return
134 - "<div class=\"config-input-check\">\n" .
135 - "<label>\n" .
136 - $this->parent->getCheckBox( $name, $value, $attribs ) . "\n" .
137 - wfMsgHtml( $label ) . "\n" .
138 - "</label>\n" .
139 - "</div>\n";
 175+ return $this->parent->getCheckBox( array(
 176+ 'var' => $var,
 177+ 'label' => $label,
 178+ 'attribs' => $attribs,
 179+ 'controlName' => $name,
 180+ 'value' => $value,
 181+ ));
140182 }
141183
142184 /**
143 - * Convenience function to set variables based on form data
144 - * Has some heuristics that may need to be overridden in child classes.
 185+ * Get a set of labelled radio buttons
 186+ *
 187+ * @param array $params
 188+ * Parameters are:
 189+ * var: The variable to be configured (required)
 190+ * label: The message name for the label (required)
 191+ * itemLabelPrefix: The message name prefix for the item labels (required)
 192+ * values: List of allowed values (required)
 193+ * itemAttribs Array of attribute arrays, outer key is the value name (optional)
 194+ *
145195 */
146 - function setVarsFromRequest() {
147 - $newValues = array();
148 - $varNames = array_merge( $this->getGlobalNames(),
149 - array_keys( $this->getInternalDefaults() ) );
150 - foreach ( $varNames as $name ) {
151 - $value = $this->parent->request->getVal( $this->getName() . '_' . $name );
152 - $newValues[$name] = $value;
153 - if ( $value !== null ) {
154 - if ( stripos( $name, 'password' ) !== false ) {
155 - $this->parent->setPassword( $name, $value );
156 - } else {
157 - $this->parent->setVar( $name, $value );
158 - }
159 - }
 196+ function getRadioSet( $params ) {
 197+ $params['controlName'] = $this->getName() . '_' . $params['var'];
 198+ $params['value'] = $this->getVar( $params['var'] );
 199+ return $this->parent->getRadioSet( $params );
 200+ }
 201+
 202+ /**
 203+ * Convenience function to set variables based on form data.
 204+ * Assumes that variables containing "password" in the name are (potentially
 205+ * fake) passwords.
 206+ * @param array $varNames
 207+ */
 208+ function setVarsFromRequest( $varNames ) {
 209+ return $this->parent->setVarsFromRequest( $varNames, $this->getName() . '_' );
 210+ }
 211+
 212+ /**
 213+ * Determine whether an existing installation of MediaWiki is present in
 214+ * the configured administrative connection. Returns true if there is
 215+ * such a wiki, false if the database doesn't exist.
 216+ *
 217+ * Traditionally, this is done by testing for the existence of either
 218+ * the revision table or the cur table.
 219+ *
 220+ * @return boolean
 221+ */
 222+ function needsUpgrade() {
 223+ $status = $this->getConnection();
 224+ if ( !$status->isOK() ) {
 225+ return false;
160226 }
161 - return $newValues;
 227+ $conn = $status->value;
 228+ if ( !$conn->selectDB( $this->getVar( 'wgDBname' ) ) ) {
 229+ return false;
 230+ }
 231+ return $conn->tableExists( 'cur' ) || $conn->tableExists( 'revision' );
162232 }
 233+
 234+ /**
 235+ * Get a standard install-user fieldset
 236+ */
 237+ function getInstallUserBox() {
 238+ return
 239+ Xml::openElement( 'fieldset' ) .
 240+ Xml::element( 'legend', array(), wfMsg( 'config-db-install-account' ) ) .
 241+ $this->getTextBox( '_InstallUser', 'config-db-username' ) .
 242+ $this->getPasswordBox( '_InstallPassword', 'config-db-password' ) .
 243+ $this->parent->getHelpBox( 'config-db-install-help' ) .
 244+ Xml::closeElement( 'fieldset' );
 245+ }
 246+
 247+ /**
 248+ * Submit a standard install user fieldset
 249+ */
 250+ function submitInstallUserBox() {
 251+ $this->setVarsFromRequest( array( '_InstallUser', '_InstallPassword' ) );
 252+ return Status::newGood();
 253+ }
 254+
 255+ /**
 256+ * Get a standard web-user fieldset
 257+ * @param string $noCreateMsg Message to display instead of the creation checkbox.
 258+ * Set this to false to show a creation checkbox.
 259+ */
 260+ function getWebUserBox( $noCreateMsg = false ) {
 261+ $name = $this->getName();
 262+ $js = "disableControlArray( \"{$name}__SameAccount\", " .
 263+ "[\"{$name}_wgDBuser\", \"{$name}_wgDBpassword\", \"{$name}__CreateDBAccount\"] )";
 264+ $s = Xml::openElement( 'fieldset' ) .
 265+ Xml::element( 'legend', array(), wfMsg( 'config-db-web-account' ) ) .
 266+ $this->getCheckBox(
 267+ '_SameAccount', 'config-db-web-account-same', array( 'onclick' => $js )
 268+ ) .
 269+ "<br/>\n" .
 270+ $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
 271+ $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
 272+ $this->parent->getHelpBox( 'config-db-web-help' );
 273+ if ( $noCreateMsg ) {
 274+ $s .= $this->parent->getHelpBox( $noCreateMsg );
 275+ } else {
 276+ $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
 277+ }
 278+ $s .= Xml::closeElement( 'fieldset' ) .
 279+ "<script type=\"text/javascript\">$js</script>";
 280+ return $s;
 281+ }
 282+
 283+ /**
 284+ * Submit the form from getWebUserBox().
 285+ * @return Status
 286+ */
 287+ function submitWebUserBox() {
 288+ $this->setVarsFromRequest( array( 'wgDBuser', 'wgDBpassword',
 289+ '_SameAccount', '_CreateDBAccount' ) );
 290+ if ( $this->getVar( '_SameAccount' ) ) {
 291+ $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
 292+ $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
 293+ }
 294+ return Status::newGood();
 295+ }
 296+
163297 }
164298
Index: branches/new-installer/phase3/includes/SkinTemplate.php
@@ -143,6 +143,7 @@
144144 global $wgPageShowWatchingUsers;
145145 global $wgUseTrackbacks, $wgUseSiteJs;
146146 global $wgArticlePath, $wgScriptPath, $wgServer, $wgLang, $wgCanonicalNamespaceNames;
 147+ global $wgLogoHeight;
147148
148149 wfProfileIn( __METHOD__ );
149150
@@ -264,6 +265,11 @@
265266 $tpl->setRef( 'scriptpath', $wgScriptPath );
266267 $tpl->setRef( 'serverurl', $wgServer );
267268 $tpl->setRef( 'logopath', $wgLogo );
 269+ if ( strval( $wgLogo ) == '' ) {
 270+ $tpl->set( 'logoHeight', 10 );
 271+ } else {
 272+ $tpl->set( 'logoHeight', $wgLogoHeight );
 273+ }
268274 $tpl->setRef( "lang", $wgContLanguageCode );
269275 $tpl->set( 'dir', $wgContLang->isRTL() ? "rtl" : "ltr" );
270276 $tpl->set( 'rtl', $wgContLang->isRTL() );
Index: branches/new-installer/phase3/includes/DefaultSettings.php
@@ -155,12 +155,14 @@
156156 $wgUploadPath = false; ///< defaults to "{$wgScriptPath}/images"
157157 $wgUploadDirectory = false; ///< defaults to "{$IP}/images"
158158 $wgHashedUploadDirectory = true;
159 -$wgLogo = false; ///< defaults to "{$wgStylePath}/common/images/wiki.png"
 159+$wgLogo = false;
 160+$wgLogoHeight = 135;
160161 $wgFavicon = '/favicon.ico';
161162 $wgAppleTouchIcon = false; ///< This one'll actually default to off. For iPhone and iPod Touch web app bookmarks
162163 $wgMathPath = false; ///< defaults to "{$wgUploadPath}/math"
163164 $wgMathDirectory = false; ///< defaults to "{$wgUploadDirectory}/math"
164165 $wgTmpDirectory = false; ///< defaults to "{$wgUploadDirectory}/tmp"
 166+$wgDeletedDirectory = false; ///< defaults to "{$wgUploadDirectory}/deleted"
165167 $wgUploadBaseUrl = "";
166168 /**@}*/
167169
@@ -177,7 +179,7 @@
178180 *
179181 */
180182 $wgFileStore = array();
181 -$wgFileStore['deleted']['directory'] = false;///< Defaults to $wgUploadDirectory/deleted
 183+$wgFileStore['deleted']['directory'] = false;///< Defaults to $wgDeletedDirectory
182184 $wgFileStore['deleted']['url'] = null; ///< Private
183185 $wgFileStore['deleted']['hash'] = 3; ///< 3-level subdirectory split
184186
Index: branches/new-installer/phase3/config/new-index.php
@@ -4,15 +4,20 @@
55 define( 'MW_CONFIG_CALLBACK', 'wfInstallerConfig' );
66
77 function wfInstallerConfig() {
 8+ // Don't access the database
89 $GLOBALS['wgUseDatabaseMessages'] = false;
910 $GLOBALS['wgLBFactoryConf'] = array( 'class' => 'LBFactory_InstallerFake' );
 11+ // Debug-friendly
1012 $GLOBALS['wgShowExceptionDetails'] = true;
 13+ // Don't break forms
 14+ $GLOBALS['wgExternalLinkTarget'] = '_blank';
1115 }
1216
1317 chdir( ".." );
1418 require( './includes/WebStart.php' );
1519
1620 $installer = new WebInstaller( $wgRequest );
 21+$wgParser->setHook( 'doclink', array( $installer, 'docLink' ) );
1722
1823 if ( !$installer->startSession() ) {
1924 $installer->finish();
@@ -30,6 +35,9 @@
3136 }
3237 $wgLang = Language::factory( $langCode );
3338
 39+$wgMetaNamspace = $wgCanonicalNamespaceNames[NS_PROJECT];
 40+
3441 $session = $installer->execute( $session );
 42+
3543 $_SESSION['installData'] = $session;
3644
Index: branches/new-installer/phase3/languages/messages/MessagesEn.php
@@ -3710,6 +3710,8 @@
37113711 Please restart the installation process.',
37123712 'config-no-session' => 'Your session data was lost!
37133713 Please check your php.ini and make sure session.save_path is set to an appropriate directory.',
 3714+'config-show-help' => 'Help',
 3715+'config-hide-help' => 'Hide help',
37143716 'config-your-language' => 'Your language:',
37153717 'config-your-language-help' => 'Select a language to use during the installation process',
37163718 'config-wiki-language' => 'Wiki language:',
@@ -3717,25 +3719,51 @@
37183720 'config-back' => '< Back',
37193721 'config-continue' => 'Continue >',
37203722 'config-page-language' => 'Language',
3721 -'config-page-environment' => 'Environment',
 3723+'config-page-welcome' => 'Welcome',
37223724 'config-page-dbconnect' => 'Connect to DB',
37233725 'config-page-upgrade' => 'Upgrade existing',
37243726 'config-page-dbsettings' => 'DB settings',
3725 -'config-page-identity' => 'Identity',
3726 -'config-page-license' => 'License',
3727 -'config-page-email' => 'Email',
 3727+'config-page-name' => 'Name',
 3728+'config-page-options' => 'Options',
37283729 'config-page-install' => 'Install',
37293730 'config-page-complete' => 'Complete!',
37303731 'config-page-restart' => 'Restart installation',
 3732+'config-page-readme' => 'Read me',
 3733+'config-page-releasenotes' => 'Release notes',
 3734+'config-page-copying' => 'Copying',
37313735 'config-help-restart' => 'Do you want to clear all saved data that you have entered, and restart the installation process?',
37323736 'config-restart' => 'Yes, restart it',
 3737+'config-welcome' => 'Welcome to MediaWiki!
37333738
 3739+=== Technical data ===
 3740+
 3741+Below is some technical data that you can provide to us if you need help during installation.',
 3742+'config-copyright' => "
 3743+=== Copyright and Terms ===
 3744+
 3745+MediaWiki is Copyright © 2001-2008 by Magnus Manske, Brion Vibber, Lee Daniel Crocker, Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason, Niklas Laxström, Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor, Aaron Schulz and others.
 3746+
 3747+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.
 3748+
 3749+This program is distributed in the hope that it will be useful, but <strong>without any warranty</strong>; without even the implied warranty of <strong>merchantability</strong> or <strong>fitness for a particular purpose</strong>. See the GNU General Public License for more details.
 3750+
 3751+You should have received <doclink href=Copying>a copy of the GNU General Public License</doclink> along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or [http://www.gnu.org/copyleft/gpl.html read it online].
 3752+",
 3753+'config-sidebar' => "
 3754+* [http://www.mediawiki.org MediaWiki home]
 3755+* <doclink href=Readme>Readme</doclink>
 3756+* <doclink href=ReleaseNotes>Release notes</doclink>
 3757+* [http://www.mediawiki.org/wiki/Help:Contents User's Guide]
 3758+* [http://www.mediawiki.org/wiki/Manual:Contents Administrator's Guide]
 3759+* [http://www.mediawiki.org/wiki/Manual:FAQ FAQ]
 3760+",
37343761 'config-env-good' => '<span class="success-message">Environment checked. You can install MediaWiki.</span>',
37353762 'config-env-bad' => 'Cannot install MediaWiki.',
37363763 'config-env-php' => 'PHP $1 installed',
37373764 'config-no-db' => 'Could not find a suitable database driver!',
37383765 'config-no-db-help' => 'You need to install a database driver for PHP.
37393766 The following database types are supported: $1.
 3767+
37403768 If you are on shared hosting, ask your hosting provider to install a suitable database driver.
37413769 If you compiled PHP yourself, reconfigure it with a database client enabled, for example using the ./configure --with-mysql.
37423770 If you installed PHP from a Debian or Ubuntu package, then you also need install the php5-mysql module.',
@@ -3787,10 +3815,12 @@
37883816 'config-db-type' => 'DB type:',
37893817 'config-db-host' => 'DB host:',
37903818 'config-db-host-help' => 'If your database server isn\'t on your web server, enter the name or IP address here.
 3819+
37913820 If you are using a shared web host, your hosting provider should give you the correct host name in their documentation.',
37923821 'config-db-wiki-settings' => 'Identify this wiki',
37933822 'config-db-name' => 'DB name:',
37943823 'config-db-name-help' => 'Choose a name that identifies your wiki. It should not contain spaces or hyphens.
 3824+
37953825 If you are using a shared host, your hosting provider will either give you a specific database name to use, or let you create databases via a control panel.',
37963826 'config-db-install-account' => 'User account for installation',
37973827 'config-db-username' => 'DB username:',
@@ -3860,12 +3890,112 @@
38613891
38623892 'config-db-web-account' => 'DB account for web access',
38633893 'config-db-web-help' => 'Select the username and password that the web server will use to connect to the database server, during ordinary operation of the wiki.
3864 -
3865 -If the account specified does not exist, the installer will attempt to create it.
38663894 ',
38673895 'config-db-web-account-same' => 'Use the same account as for installation',
 3896+'config-db-web-create' => 'Create the account if it doesn\'t already exist',
 3897+'config-db-web-no-create-privs' => 'The account you specified for installation does not have enough privileges to safely create accounts, so the account you specify here must already exist.',
 3898+'config-mysql-engine' => 'Storage engine',
 3899+'config-mysql-innodb' => 'InnoDB',
 3900+'config-mysql-myisam' => 'MyISAM',
 3901+'config-mysql-engine-help' => '<strong>InnoDB</strong> is best for public web installations, since it has good concurrency support.
38683902
 3903+<strong>MyISAM</strong> may be faster in single-user installations. MyISAM databases tend to get corrupted more often than InnoDB databases.
 3904+',
 3905+'config-mysql-charset' => 'Database character set',
 3906+'config-mysql-binary' => 'Binary',
 3907+'config-mysql-utf-8' => 'UTF-8',
 3908+'config-mysql-charset-help' => "In '''binary mode''', MediaWiki stores UTF-8 text to the database in binary fields. This is more efficient than MySQL's UTF-8 mode, and allows you to use the full range of Unicode characters.
38693909
 3910+In '''UTF-8 mode''', MySQL will know what character set your data is in, and can present and convert it appropriately, but it won't let you store characters above the [http://en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane]. ",
 3911+'config-site-name' => 'Name of wiki:',
 3912+'config-site-name-help' => 'This will appear in the browser\'s title bar and various other places.',
 3913+'config-site-name-blank' => 'Please enter a site name.',
 3914+'config-project-namespace' => 'Project namespace',
 3915+'config-ns-generic' => 'Project',
 3916+'config-ns-site-name' => 'Same as the wiki name: ',
 3917+'config-ns-other' => 'Other (please specify)',
 3918+'config-project-namespace-help' => 'Following Wikipedia\'s example, many wikis keep their policy and help pages separate from their content pages, in a "<strong>project namespace</strong>".
 3919+All page titles in this namespace start with a certain prefix, which you can specify here.
 3920+Traditionally, this prefix is derived from the name of the wiki, but it cannot contain punctuation characters such as # or :',
 3921+'config-ns-invalid' => 'The specified namespace "<nowiki>$1</nowiki>" is invalid. Please specify a different project namespace',
 3922+'config-admin-box' => 'Administrator account',
 3923+'config-admin-name' => 'Your name:',
 3924+'config-admin-password' => 'Password:',
 3925+'config-admin-password-confirm' => 'Password again:',
 3926+'config-admin-help' => 'Enter your preferred username here, for example "Joe Bloggs".
 3927+This is the name you will use to log in to the wiki.
 3928+
 3929+The password cannot be the same as the username. ',
 3930+'config-admin-name-blank' => 'Please enter an administrator username.',
 3931+'config-admin-name-invalid' => 'The specified username "<nowiki>$1</nowiki>" is invalid. Please specify a different username.',
 3932+'config-admin-password-blank' => 'Please enter an administrator password.',
 3933+'config-admin-password-same' => 'The password must not be the same as the username.',
 3934+'config-admin-password-mismatch' => 'The two passwords you entered do not match.',
 3935+'config-admin-email' => 'Email address:',
 3936+'config-admin-email-help' => 'Enter an email address here to allow you to receive email from other users on the wiki, reset your password, and be notified of changes to pages on your watchlist.',
 3937+'config-subscribe' => 'Subscribe to the [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce release announcements mailing list].',
 3938+'config-subscribe-help' => 'This is a low-volume mailing list used for release announcements, including important security announcements.
 3939+You should subscribe to it and update your copy of MediaWiki when new versions come out.',
 3940+'config-almost-done' => "You're almost done! If you like, you can skip the remaining configuration and install the wiki right now.",
 3941+'config-optional-continue' => "Ask me more questions.",
 3942+'config-optional-skip' => "I'm bored already, just install the wiki.",
 3943+'config-profile' => 'User rights profile',
 3944+'config-profile-wiki' => 'Traditional wiki',
 3945+'config-profile-no-anon' => 'Account creation required',
 3946+'config-profile-fishbowl' => 'Fishbowl',
 3947+'config-profile-private' => 'Private wiki',
 3948+'config-profile-help' => "Wikis work best when you let as many people edit them as possible.
 3949+In MediaWiki, it's easy to review the recent changes, and to revert any damage that is done by naïve or malicious users.
 3950+
 3951+However, many people have found MediaWiki to be useful in a wide variety of roles, and sometimes it's not easy to convince everyone around you of the benefits of the wiki way. So we give you the choice.
 3952+
 3953+A '''traditional wiki''' allows anyone to edit, without even logging in. Some people prefer a wiki with '''account creation required''', since this provides extra accountability (but may deter casual contributors).
 3954+
 3955+A '''fishbowl''' only allows approved users to edit, but the public can view the pages, including history. A '''private wiki''' only allows approved users to view pages, with the same group allowed to edit.
 3956+
 3957+More complex user rights configurations are available after installation, see the [http://www.mediawiki.org/wiki/Manual:User_rights relevant manual entry].
 3958+",
 3959+'config-license' => 'Copyright/License',
 3960+'config-license-none' => 'No license footer',
 3961+'config-license-gfdl-old' => 'GNU Free Documentation License 1.2 or later',
 3962+'config-license-gfdl-current' => 'GNU Free Documentation License 1.3 or later',
 3963+'config-license-pd' => 'Public Domain',
 3964+'config-license-cc-choose' => 'A Creative Commons license',
 3965+'config-license-help' => 'Many public wikis put all contributions under a [http://freedomdefined.org/Definition free license].
 3966+This helps to create a sense of community ownership and encourages long-term contribution.
 3967+It is not generally necessary for a private or corporate wiki.
 3968+
 3969+If you want to be able to use text from Wikipedia, and you want Wikipedia to be able to accept text copied from your wiki, you should choose <strong>GNU Free Documentation License 1.2</strong>.
 3970+However, this license has some features which make reuse and interpretation difficult.
 3971+
 3972+If Wikipedia-compatibility is not important, <strong>Creative Commons</strong> with the <strong>Share Alike</strong> option (cc-by-sa) is a good choice.
 3973+',
 3974+'config-email-settings' => 'Email settings',
 3975+'config-enable-email' => 'Enable outbound email',
 3976+'config-enable-email-help' => "If you want email to work, [http://au2.php.net/manual/en/mail.configuration.php PHP's mail settings] need to be configured correctly.
 3977+If you don't want any email features, you can disable it here.",
 3978+'config-email-sender' => 'Return address:',
 3979+'config-email-sender-help' => 'Enter the email address to use as the return address on outbound email.
 3980+This is where bounces will be sent.
 3981+Many mail servers require at least the domain name part to be valid.',
 3982+'config-upload-settings' => 'Images and file uploads',
 3983+'config-upload-enable' => 'Enable file uploads',
 3984+'config-upload-help' => "File uploads potentially expose your server to security risks.
 3985+For more information, read the [http://www.mediawiki.org/wiki/Manual:Security security section] in the manual.
 3986+
 3987+To enable uploads, change the mode on the <tt>images</tt> subdirectory under MediaWiki's root directory so that the web server can write to it. Then enable this option.",
 3988+'config-upload-deleted' => 'Deleted directory:',
 3989+'config-upload-deleted-help' => 'Choose a directory in which to archive deleted files.
 3990+Ideally, this should not be publically accessible.',
 3991+'config-logo' => 'Logo URL:',
 3992+'config-logo-help' => "MediaWiki's default skin includes space for a 135x135 pixel logo in the top left corner.
 3993+Upload an image of the appropriate size, and enter the URL here.
 3994+
 3995+If you don't want a logo, leave this box blank.",
 3996+'config-cc-error' => 'The Creative Commons license chooser gave no result. Please enter the license name manually.',
 3997+'config-cc-again' => 'Pick again...',
 3998+'config-cc-not-chosen' => 'Please choose which Creative Commons license you want and click "proceed".',
 3999+
38704000 # Special:Version
38714001 'version' => 'Version', # Not used as normal message but as header for the special page itself
38724002 'version-extensions' => 'Installed extensions',

Follow-up revisions

RevisionCommit summaryAuthorDate
r79491Fix for r45497: undefined variableialex14:35, 2 January 2011
r89311Make user right selection in installer actually work, thanks Krinkle for spot...demon01:26, 2 June 2011

Comments

#Comment by 😂 (talk | contribs)   22:03, 28 February 2011

I'm curious about the usefulness of making $wgDeletedDirectory installer-configurable. The vast majority of people using MediaWiki are doing so on shared hosting, so are unlikely to be able to specify a path outside of their htdocs. I see the benefit in promoting security, but it seems likely to cause confusion more than anything.

Cf bug 26937.

#Comment by 😂 (talk | contribs)   22:06, 28 February 2011

Bug is completely unrelated, ignore that part.

#Comment by Krinkle (talk | contribs)   12:11, 1 June 2011

Looks like this commit introduced the following "feature":

 
 	/**
+	 * User rights profiles
+	 */
+	var $rightsProfiles = array(	
+		'wiki' => array(),
+		'no-anon' => array(
+			'*' => array( 'edit' => false )
+		),
+		'fishbowl' => array(
+			'*' => array( 
+				'createaccount' => false,
+				'edit' => false,
+			),
+		),
+		'private' => array(
+			'*' => array(
+				'createaccount' => false,
+				'edit' => false,
+				'read' => false,
+			),
+		),
+	);

However, in the current 1.19 svn HEAD this is not working (maybe it never did), these values are ignored and not put into the LocalSettings.php write/download.

This variable and it's storage in _RightsProfile has been moved about half a dozen times this 2009, currently it's used in three places

I guess the part that's missing is some kind of loop that sets values overriding parts of $wgGroupPermissions .

I'm asking here to verify that it was introduced here, and that it never worked.

Or does it ?

#Comment by Tim Starling (talk | contribs)   01:05, 2 June 2011

The idea was that it would cause $wgGroupPermissions to be set in the generated LocalSettings.php to a suitable set of permissions. It certainly didn't work at the time, because the code to generate LocalSettings.php was not done at the time. It was written later, by Chad.

If the rights profile is still in the UI but it doesn't do anything, a 1.17 blocker bug should be opened immediately.

#Comment by Krinkle (talk | contribs)   00:24, 10 June 2011

That was indeed the case.

Chad fixed it in r89311.

Status & tagging log