Index: trunk/phase3/maintenance/install.php |
— | — | @@ -20,35 +20,41 @@ |
21 | 21 | * @see wfWaitForSlaves() |
22 | 22 | */ |
23 | 23 | |
24 | | -define( 'MW_NO_DB', 1 ); |
25 | | -define( 'MW_NO_SESSION', 1 ); |
26 | | -define( 'MW_CONFIG_CALLBACK', 'wfInstallerConfig' ); |
| 24 | +define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' ); |
27 | 25 | |
28 | | -$IP = dirname( dirname( __FILE__ ) ); |
| 26 | +require_once( dirname( dirname( __FILE__ ) )."/maintenance/Maintenance.php" ); |
29 | 27 | |
30 | | -require_once( "$IP/maintenance/Maintenance.php" ); |
31 | | - |
32 | 28 | class CommandLineInstaller extends Maintenance { |
33 | 29 | public function __construct() { |
| 30 | + parent::__construct(); |
| 31 | + |
34 | 32 | $this->addArg( 'name', 'The name of the wiki', true); |
| 33 | + |
35 | 34 | $this->addArg( 'admin', 'The username of the wiki administrator (WikiSysop)', false); |
36 | 35 | $this->addOption( 'pass', 'The password for the wiki administrator. You will be prompted for this if it isn\'t provided', false, true); |
37 | | - /* $this->addOption( 'email', 'The email for the wiki administrator', false, true); */ |
| 36 | + $this->addOption( 'email', 'The email for the wiki administrator', false, true); |
| 37 | + |
38 | 38 | $this->addOption( 'lang', 'The language to use (en)', false, true ); |
39 | 39 | /* $this->addOption( 'cont-lang', 'The content language (en)', false, true ); */ |
40 | | - $this->addOption( 'db-type', 'The type of database (mysql)', false, true ); |
41 | | - /* $this->addOption( 'db-host', 'The database host (localhost)', false, true ); */ |
42 | | - /* $this->addOption( 'db-port', 'The database port (3306 for mysql, 5432 for pg)', false, true ); */ |
43 | | - $this->addOption( 'db-name', 'The database name (my_wiki)', false, true ); |
44 | | - $this->addOption( 'db-path', 'The path for the SQLite DB (/var/data)', false, true ); |
45 | | - /* $this->addOption( 'db-schema', 'The schema for the MediaWiki DB in pg (mediawiki)', false, true ); */ |
46 | | - /* $this->addOption( 'db-tsearch2-schema', 'The schema for the tsearch2 DB in pg (public)', false, true ); */ |
| 40 | + |
| 41 | + $this->addOption( 'dbtype', 'The type of database (mysql)', false, true ); |
| 42 | + /* $this->addOption( 'dbhost', 'The database host (localhost)', false, true ); */ |
| 43 | + /* $this->addOption( 'dbport', 'The database port (3306 for mysql, 5432 for pg)', false, true ); */ |
| 44 | + $this->addOption( 'dbname', 'The database name (my_wiki)', false, true ); |
| 45 | + $this->addOption( 'dbpath', 'The path for the SQLite DB (/var/data)', false, true ); |
| 46 | + $this->addOption( 'installdbuser', 'The user to use for installing (root)', false, true ); |
| 47 | + $this->addOption( 'installdbpass', 'The pasword for the DB user to install as.', false, true ); |
| 48 | + /* $this->addOption( 'dbschema', 'The schema for the MediaWiki DB in pg (mediawiki)', false, true ); */ |
| 49 | + /* $this->addOption( 'dbtsearch2schema', 'The schema for the tsearch2 DB in pg (public)', false, true ); */ |
47 | 50 | /* $this->addOption( 'namespace', 'The project namespace (same as the name)', false, true ); */ |
48 | 51 | } |
49 | 52 | |
50 | 53 | public function execute() { |
51 | | - $installer = new CliInstaller( $this->mArgs[0], $this->mArgs[1], $this->mOptions ); |
| 54 | + $adminName = isset( $this->mArgs[1] ) ? $this->mArgs[1] : null; |
52 | 55 | |
| 56 | + $installer = |
| 57 | + new CliInstaller( $this->mArgs[0], $adminName, $this->mOptions ); |
| 58 | + |
53 | 59 | $installer->execute(); |
54 | 60 | } |
55 | 61 | } |
Index: trunk/phase3/maintenance/doMaintenance.php |
— | — | @@ -61,9 +61,13 @@ |
62 | 62 | require_once( "$IP/includes/AutoLoader.php" ); |
63 | 63 | require_once( "$IP/includes/Defines.php" ); |
64 | 64 | |
65 | | -// Load settings, using wikimedia-mode if needed |
66 | | -// Fixme: replace this hack with general farm-friendly code |
67 | | -if ( file_exists( "$IP/wmf-config/wikimedia-mode" ) ) { |
| 65 | +if ( defined( 'MW_CONFIG_CALLBACK' ) ) { |
| 66 | + # Use a callback function to configure MediaWiki |
| 67 | + require_once( "$IP/includes/DefaultSettings.php" ); |
| 68 | + call_user_func( MW_CONFIG_CALLBACK ); |
| 69 | +} elseif ( file_exists( "$IP/wmf-config/wikimedia-mode" ) ) { |
| 70 | + // Load settings, using wikimedia-mode if needed |
| 71 | + // Fixme: replace this hack with general farm-friendly code |
68 | 72 | # TODO FIXME! Wikimedia-specific stuff needs to go away to an ext |
69 | 73 | # Maybe a hook? |
70 | 74 | global $cluster; |
— | — | @@ -76,6 +80,7 @@ |
77 | 81 | } else { |
78 | 82 | require_once( $maintenance->loadSettings() ); |
79 | 83 | } |
| 84 | + |
80 | 85 | if ( $maintenance->getDbType() === Maintenance::DB_ADMIN && |
81 | 86 | is_readable( "$IP/AdminSettings.php" ) ) |
82 | 87 | { |
Index: trunk/phase3/maintenance/Maintenance.php |
— | — | @@ -217,7 +217,8 @@ |
218 | 218 | * Throw some output to the user. Scripts can call this with no fears, |
219 | 219 | * as we handle all --quiet stuff here |
220 | 220 | * @param $out String: the text to show to the user |
221 | | - * @param $channel Mixed: unique identifier for the channel. See function outputChanneled. |
| 221 | + * @param $channel Mixed: unique identifier for the channel. See |
| 222 | + * function outputChanneled. |
222 | 223 | */ |
223 | 224 | protected function output( $out, $channel = null ) { |
224 | 225 | if ( $this->mQuiet ) { |
— | — | @@ -256,13 +257,14 @@ |
257 | 258 | |
258 | 259 | private $atLineStart = true; |
259 | 260 | private $lastChannel = null; |
260 | | - |
| 261 | + |
261 | 262 | /** |
262 | 263 | * Message outputter with channeled message support. Messages on the |
263 | 264 | * same channel are concatenated, but any intervening messages in another |
264 | 265 | * channel start a new line. |
265 | 266 | * @param $msg String: the message without trailing newline |
266 | | - * @param $channel Channel identifier or null for no channel. Channel comparison uses ===. |
| 267 | + * @param $channel Channel identifier or null for no |
| 268 | + * channel. Channel comparison uses ===. |
267 | 269 | */ |
268 | 270 | public function outputChanneled( $msg, $channel = null ) { |
269 | 271 | $handle = fopen( 'php://stdout', 'w' ); |
— | — | @@ -556,7 +558,7 @@ |
557 | 559 | $die = true; |
558 | 560 | } |
559 | 561 | } |
560 | | - |
| 562 | + |
561 | 563 | if ( $die ) { |
562 | 564 | $this->maybeHelp( true ); |
563 | 565 | } |
— | — | @@ -588,7 +590,7 @@ |
589 | 591 | $screenWidth = 80; // TODO: Caculate this! |
590 | 592 | $tab = " "; |
591 | 593 | $descWidth = $screenWidth - ( 2 * strlen( $tab ) ); |
592 | | - |
| 594 | + |
593 | 595 | ksort( $this->mParams ); |
594 | 596 | if ( $this->hasOption( 'help' ) || $force ) { |
595 | 597 | $this->mQuiet = false; |
Index: trunk/phase3/includes/installer/Installer.php |
— | — | @@ -215,6 +215,16 @@ |
216 | 216 | * Constructor, always call this from child classes |
217 | 217 | */ |
218 | 218 | function __construct() { |
| 219 | + // Disable the i18n cache and LoadBalancer |
| 220 | + Language::getLocalisationCache()->disableBackend(); |
| 221 | + LBFactory::disableBackend(); |
| 222 | + |
| 223 | + // Load the installer's i18n file |
| 224 | + global $wgExtensionMessagesFiles; |
| 225 | + $wgExtensionMessagesFiles['MediawikiInstaller'] = |
| 226 | + './includes/installer/Installer.i18n.php'; |
| 227 | + |
| 228 | + |
219 | 229 | $this->settings = $this->internalDefaults; |
220 | 230 | foreach ( $this->defaultVarNames as $var ) { |
221 | 231 | $this->settings[$var] = $GLOBALS[$var]; |
— | — | @@ -909,7 +919,7 @@ |
910 | 920 | } |
911 | 921 | } |
912 | 922 | |
913 | | - /* |
| 923 | + /** |
914 | 924 | * On POSIX systems return the primary group of the webserver we're running under. |
915 | 925 | * On other systems just returns null. |
916 | 926 | * |
— | — | @@ -934,4 +944,22 @@ |
935 | 945 | |
936 | 946 | return $group; |
937 | 947 | } |
| 948 | + |
| 949 | + /** |
| 950 | + * Override the necessary bits of the config to run an installation |
| 951 | + */ |
| 952 | + public static function overrideConfig() { |
| 953 | + define( 'MW_NO_SESSION', 1 ); |
| 954 | + |
| 955 | + // Don't access the database |
| 956 | + $GLOBALS['wgUseDatabaseMessages'] = false; |
| 957 | + // Debug-friendly |
| 958 | + $GLOBALS['wgShowExceptionDetails'] = true; |
| 959 | + // Don't break forms |
| 960 | + $GLOBALS['wgExternalLinkTarget'] = '_blank'; |
| 961 | + |
| 962 | + // Extended debugging. Maybe disable before release? |
| 963 | + $GLOBALS['wgShowSQLErrors'] = true; |
| 964 | + $GLOBALS['wgShowDBErrorBacktrace'] = true; |
| 965 | + } |
938 | 966 | } |
Index: trunk/phase3/includes/installer/CliInstaller.php |
— | — | @@ -1,24 +1,41 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | | -function wfInstallerConfig() { |
5 | | - // Don't access the database |
6 | | - $GLOBALS['wgUseDatabaseMessages'] = false; |
7 | | - // Debug-friendly |
8 | | - $GLOBALS['wgShowExceptionDetails'] = true; |
9 | | - // Don't break forms |
10 | | - $GLOBALS['wgExternalLinkTarget'] = '_blank'; |
| 4 | +class CliInstaller extends Installer { |
11 | 5 | |
12 | | - // Extended debugging. Maybe disable before release? |
13 | | - $GLOBALS['wgShowSQLErrors'] = true; |
14 | | - $GLOBALS['wgShowDBErrorBacktrace'] = true; |
15 | | -} |
| 6 | + /* The maintenance class in effect */ |
| 7 | + private $maint; |
16 | 8 | |
17 | | -class CliInstaller extends Installer { |
| 9 | + private $optionMap = array( |
| 10 | + 'dbtype' => 'wgDBtype', |
| 11 | + 'dbserver' => 'wgDBserver', |
| 12 | + 'dbname' => 'wgDBname', |
| 13 | + 'dbuser' => 'wgDBuser', |
| 14 | + 'dbpass' => 'wgDBpassword', |
| 15 | + 'dbprefix' => 'wgDBprefix', |
| 16 | + 'dbtableoptions' => 'wgDBTableOptions', |
| 17 | + 'dbmysql5' => 'wgDBmysql5', |
| 18 | + 'dbserver' => 'wgDBserver', |
| 19 | + 'dbport' => 'wgDBport', |
| 20 | + 'dbname' => 'wgDBname', |
| 21 | + 'dbuser' => 'wgDBuser', |
| 22 | + 'dbpass' => 'wgDBpassword', |
| 23 | + 'dbschema' => 'wgDBmwschema', |
| 24 | + 'dbts2schema' => 'wgDBts2schema', |
| 25 | + 'dbpath' => 'wgSQLiteDataDir', |
| 26 | + ); |
18 | 27 | |
| 28 | + |
19 | 29 | /** Constructor */ |
20 | 30 | function __construct( $siteName, $admin = null, $option = array()) { |
21 | 31 | parent::__construct(); |
22 | 32 | |
| 33 | + foreach ( $this->optionMap as $opt => $global ) { |
| 34 | + if ( isset( $option[$opt] ) ) { |
| 35 | + $GLOBALS[$global] = $option[$opt]; |
| 36 | + $this->setVar( $global, $option[$opt] ); |
| 37 | + } |
| 38 | + } |
| 39 | + |
23 | 40 | if ( isset( $option['lang'] ) ) { |
24 | 41 | global $wgLang, $wgContLang, $wgLanguageCode; |
25 | 42 | $this->setVar( '_UserLang', $option['lang'] ); |
— | — | @@ -31,22 +48,48 @@ |
32 | 49 | if ( $admin ) { |
33 | 50 | $this->setVar( '_AdminName', $admin ); |
34 | 51 | } else { |
35 | | - $this->setVar( '_AdminName', wfMsgForContent( 'config-admin-default-username' ) ); |
| 52 | + $this->setVar( '_AdminName', |
| 53 | + wfMsgForContent( 'config-admin-default-username' ) ); |
36 | 54 | } |
| 55 | + |
| 56 | + if ( !isset( $option['installdbuser'] ) ) { |
| 57 | + $this->setVar( '_InstallUser', |
| 58 | + $this->getVar( 'wgDBuser' ) ); |
| 59 | + $this->setVar( '_InstallPassword', |
| 60 | + $this->getVar( 'wgDBpassword' ) ); |
| 61 | + } |
| 62 | + |
| 63 | + if ( isset( $option['pass'] ) ) { |
| 64 | + $this->setVar( '_AdminPassword', $option['pass'] ); |
| 65 | + } |
| 66 | + |
| 67 | + $this->output = new CliInstallerOutput( $this ); |
37 | 68 | } |
38 | 69 | |
39 | 70 | /** |
40 | 71 | * Main entry point. |
41 | 72 | */ |
42 | 73 | function execute( ) { |
43 | | - var_dump($this->getVar('_AdminName')); |
| 74 | + foreach( $this->getInstallSteps() as $step ) { |
| 75 | + $this->showMessage("Installing $step... "); |
| 76 | + $func = 'install' . ucfirst( $step ); |
| 77 | + $status = $this->{$func}(); |
| 78 | + $ok = $status->isGood(); |
| 79 | + if ( !$ok ) { |
| 80 | + $this->showStatusError( $status ); |
| 81 | + exit; |
| 82 | + } |
| 83 | + $this->showMessage("done\n"); |
| 84 | + } |
44 | 85 | } |
45 | 86 | |
46 | 87 | function showMessage( $msg /*, ... */ ) { |
47 | | - echo "Message: $msg\n"; |
| 88 | + $this->output->addHTML($msg); |
| 89 | + $this->output->output(); |
48 | 90 | } |
49 | 91 | |
50 | 92 | function showStatusError( $status ) { |
51 | | - echo "Error: $status\n"; |
| 93 | + $this->output->addHTML($status->getWikiText()."\n"); |
| 94 | + $this->output->flush(); |
52 | 95 | } |
53 | 96 | } |
Index: trunk/phase3/includes/installer/CliInstallerOutput.php |
— | — | @@ -0,0 +1,83 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Output class modelled on OutputPage. |
| 6 | + * |
| 7 | + * I've opted to use a distinct class rather than derive from OutputPage here in |
| 8 | + * the interests of separation of concerns: if we used a subclass, there would be |
| 9 | + * quite a lot of things you could do in OutputPage that would break the installer, |
| 10 | + * that wouldn't be immediately obvious. |
| 11 | + */ |
| 12 | +class CliInstallerOutput { |
| 13 | + |
| 14 | + function __construct( $parent ) { |
| 15 | + $this->parent = $parent; |
| 16 | + } |
| 17 | + |
| 18 | + function addHTML( $html ) { |
| 19 | + $this->contents .= $html; |
| 20 | + } |
| 21 | + |
| 22 | + function addWikiText( $text ) { |
| 23 | + $this->addHTML( $this->parent->parse( $text ) ); |
| 24 | + } |
| 25 | + |
| 26 | + function addHTMLNoFlush( $html ) { |
| 27 | + $this->contents .= $html; |
| 28 | + } |
| 29 | + |
| 30 | + function addWarning( $msg ) { |
| 31 | + $this->warnings .= "<p>$msg</p>\n"; |
| 32 | + } |
| 33 | + |
| 34 | + function addWarningMsg( $msg /*, ... */ ) { |
| 35 | + $params = func_get_args(); |
| 36 | + array_shift( $params ); |
| 37 | + $this->addWarning( wfMsg( $msg, $params ) ); |
| 38 | + } |
| 39 | + |
| 40 | + function redirect( $url ) { |
| 41 | + if ( $this->headerDone ) { |
| 42 | + throw new MWException( __METHOD__ . ' called after sending headers' ); |
| 43 | + } |
| 44 | + $this->redirectTarget = $url; |
| 45 | + } |
| 46 | + |
| 47 | + function output() { |
| 48 | + $this->flush(); |
| 49 | + $this->outputFooter(); |
| 50 | + } |
| 51 | + |
| 52 | + function useShortHeader( $use = true ) { |
| 53 | + } |
| 54 | + |
| 55 | + function flush() { |
| 56 | + echo $this->contents; |
| 57 | + flush(); |
| 58 | + $this->contents = ''; |
| 59 | + } |
| 60 | + |
| 61 | + function getDir() { |
| 62 | + global $wgLang; |
| 63 | + if( !is_object( $wgLang ) || !$wgLang->isRtl() ) |
| 64 | + return 'ltr'; |
| 65 | + else |
| 66 | + return 'rtl'; |
| 67 | + } |
| 68 | + |
| 69 | + function getLanguageCode() { |
| 70 | + global $wgLang; |
| 71 | + if( !is_object( $wgLang ) ) |
| 72 | + return 'en'; |
| 73 | + else |
| 74 | + return $wgLang->getCode(); |
| 75 | + } |
| 76 | + |
| 77 | + function outputWarnings() { |
| 78 | + $this->addHTML( $this->warnings ); |
| 79 | + $this->warnings = ''; |
| 80 | + } |
| 81 | + |
| 82 | + function outputFooter() {} |
| 83 | + |
| 84 | +} |
Property changes on: trunk/phase3/includes/installer/CliInstallerOutput.php |
___________________________________________________________________ |
Added: svn:eol-syle |
1 | 85 | + native |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -414,6 +414,7 @@ |
415 | 415 | |
416 | 416 | # includes/installer |
417 | 417 | 'CliInstaller' => 'includes/installer/CliInstaller.php', |
| 418 | + 'CliInstallerOutput' => 'includes/installer/CliInstallerOutput.php', |
418 | 419 | 'Installer' => 'includes/installer/Installer.php', |
419 | 420 | 'InstallerDBType' => 'includes/installer/InstallerDBType.php', |
420 | 421 | 'LBFactory_InstallerFake' => 'includes/installer/Installer.php', |
Index: trunk/phase3/config/new-index.php |
— | — | @@ -1,35 +1,12 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | | -define( 'MW_NO_DB', 1 ); |
5 | | -define( 'MW_NO_SESSION', 1 ); |
6 | | -define( 'MW_CONFIG_CALLBACK', 'wfInstallerConfig' ); |
| 4 | +define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' ); |
7 | 5 | |
8 | | -function wfInstallerConfig() { |
9 | | - // Don't access the database |
10 | | - $GLOBALS['wgUseDatabaseMessages'] = false; |
11 | | - // Debug-friendly |
12 | | - $GLOBALS['wgShowExceptionDetails'] = true; |
13 | | - // Don't break forms |
14 | | - $GLOBALS['wgExternalLinkTarget'] = '_blank'; |
15 | | - |
16 | | - // Extended debugging. Maybe disable before release? |
17 | | - $GLOBALS['wgShowSQLErrors'] = true; |
18 | | - $GLOBALS['wgShowDBErrorBacktrace'] = true; |
19 | | -} |
20 | | - |
21 | 6 | chdir( ".." ); |
22 | 7 | require( './includes/WebStart.php' ); |
23 | 8 | require_once( './maintenance/updaters.inc' ); // sigh... |
24 | 9 | |
25 | | -// Disable the i18n cache and LoadBalancer |
26 | | -Language::getLocalisationCache()->disableBackend(); |
27 | | -LBFactory::disableBackend(); |
28 | | - |
29 | | -// Load the installer's i18n file |
30 | | -$wgExtensionMessagesFiles['MediawikiInstaller'] = './includes/installer/Installer.i18n.php'; |
31 | | - |
32 | 10 | $installer = new WebInstaller( $wgRequest ); |
33 | | -$wgParser->setHook( 'doclink', array( $installer, 'docLink' ) ); |
34 | 11 | |
35 | 12 | if ( !$installer->startSession() ) { |
36 | 13 | $installer->finish(); |