Completed
Branch master (939199)
by
unknown
39:35
created

includes/installer/LocalSettingsGenerator.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Generator for LocalSettings.php file.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup Deployment
22
 */
23
24
/**
25
 * Class for generating LocalSettings.php file.
26
 *
27
 * @ingroup Deployment
28
 * @since 1.17
29
 */
30
class LocalSettingsGenerator {
31
32
	protected $extensions = [];
33
	protected $values = [];
34
	protected $groupPermissions = [];
35
	protected $dbSettings = '';
36
	protected $IP;
37
38
	/**
39
	 * @var Installer
40
	 */
41
	protected $installer;
42
43
	/**
44
	 * Constructor.
45
	 *
46
	 * @param Installer $installer
47
	 */
48
	public function __construct( Installer $installer ) {
49
		$this->installer = $installer;
50
51
		$this->extensions = $installer->getVar( '_Extensions' );
52
		$this->skins = $installer->getVar( '_Skins' );
53
		$this->IP = $installer->getVar( 'IP' );
54
55
		$db = $installer->getDBInstaller( $installer->getVar( 'wgDBtype' ) );
56
57
		$confItems = array_merge(
58
			[
59
				'wgServer', 'wgScriptPath',
60
				'wgPasswordSender', 'wgImageMagickConvertCommand', 'wgShellLocale',
61
				'wgLanguageCode', 'wgEnableEmail', 'wgEnableUserEmail', 'wgDiff3',
62
				'wgEnotifUserTalk', 'wgEnotifWatchlist', 'wgEmailAuthentication',
63
				'wgDBtype', 'wgSecretKey', 'wgRightsUrl', 'wgSitename', 'wgRightsIcon',
64
				'wgRightsText', '_MainCacheType', 'wgEnableUploads',
65
				'_MemCachedServers', 'wgDBserver', 'wgDBuser',
66
				'wgDBpassword', 'wgUseInstantCommons', 'wgUpgradeKey', 'wgDefaultSkin',
67
				'wgMetaNamespace', 'wgLogo', 'wgAuthenticationTokenVersion', 'wgPingback',
68
			],
69
			$db->getGlobalNames()
70
		);
71
72
		$unescaped = [ 'wgRightsIcon', 'wgLogo' ];
73
		$boolItems = [
74
			'wgEnableEmail', 'wgEnableUserEmail', 'wgEnotifUserTalk',
75
			'wgEnotifWatchlist', 'wgEmailAuthentication', 'wgEnableUploads', 'wgUseInstantCommons',
76
			'wgPingback',
77
		];
78
79
		foreach ( $confItems as $c ) {
80
			$val = $installer->getVar( $c );
81
82
			if ( in_array( $c, $boolItems ) ) {
83
				$val = wfBoolToStr( $val );
84
			}
85
86
			if ( !in_array( $c, $unescaped ) && $val !== null ) {
87
				$val = self::escapePhpString( $val );
88
			}
89
90
			$this->values[$c] = $val;
91
		}
92
93
		$this->dbSettings = $db->getLocalSettings();
94
		$this->values['wgEmergencyContact'] = $this->values['wgPasswordSender'];
95
	}
96
97
	/**
98
	 * For $wgGroupPermissions, set a given ['group']['permission'] value.
99
	 * @param string $group Group name
100
	 * @param array $rightsArr An array of permissions, in the form of:
101
	 *   [ 'right' => true, 'right2' => false ]
102
	 */
103
	public function setGroupRights( $group, $rightsArr ) {
104
		$this->groupPermissions[$group] = $rightsArr;
105
	}
106
107
	/**
108
	 * Returns the escaped version of a string of php code.
109
	 *
110
	 * @param string $string
111
	 *
112
	 * @return string
113
	 */
114 View Code Duplication
	public static function escapePhpString( $string ) {
115
		if ( is_array( $string ) || is_object( $string ) ) {
116
			return false;
117
		}
118
119
		return strtr(
120
			$string,
121
			[
122
				"\n" => "\\n",
123
				"\r" => "\\r",
124
				"\t" => "\\t",
125
				"\\" => "\\\\",
126
				"\$" => "\\\$",
127
				"\"" => "\\\""
128
			]
129
		);
130
	}
131
132
	/**
133
	 * Return the full text of the generated LocalSettings.php file,
134
	 * including the extensions and skins.
135
	 *
136
	 * @return string
137
	 */
138
	public function getText() {
139
		$localSettings = $this->getDefaultText();
140
141 View Code Duplication
		if ( count( $this->skins ) ) {
142
			$localSettings .= "
143
# Enabled skins.
144
# The following skins were automatically enabled:\n";
145
146
			foreach ( $this->skins as $skinName ) {
147
				$localSettings .= $this->generateExtEnableLine( 'skins', $skinName );
148
			}
149
150
			$localSettings .= "\n";
151
		}
152
153 View Code Duplication
		if ( count( $this->extensions ) ) {
154
			$localSettings .= "
155
# Enabled extensions. Most of the extensions are enabled by adding
156
# wfLoadExtensions('ExtensionName');
157
# to LocalSettings.php. Check specific extension documentation for more details.
158
# The following extensions were automatically enabled:\n";
159
160
			foreach ( $this->extensions as $extName ) {
161
				$localSettings .= $this->generateExtEnableLine( 'extensions', $extName );
162
			}
163
164
			$localSettings .= "\n";
165
		}
166
167
		$localSettings .= "
168
# End of automatically generated settings.
169
# Add more configuration options below.\n\n";
170
171
		return $localSettings;
172
	}
173
174
	/**
175
	 * Generate the appropriate line to enable the given extension or skin
176
	 *
177
	 * @param string $dir Either "extensions" or "skins"
178
	 * @param string $name Name of extension/skin
179
	 * @throws InvalidArgumentException
180
	 * @return string
181
	 */
182
	private function generateExtEnableLine( $dir, $name ) {
183
		if ( $dir === 'extensions' ) {
184
			$jsonFile = 'extension.json';
185
			$function = 'wfLoadExtension';
186
		} elseif ( $dir === 'skins' ) {
187
			$jsonFile = 'skin.json';
188
			$function = 'wfLoadSkin';
189
		} else {
190
			throw new InvalidArgumentException( '$dir was not "extensions" or "skins' );
191
		}
192
193
		$encName = self::escapePhpString( $name );
194
195
		if ( file_exists( "{$this->IP}/$dir/$encName/$jsonFile" ) ) {
196
			return "$function( '$encName' );\n";
197
		} else {
198
			return "require_once \"\$IP/$dir/$encName/$encName.php\";\n";
199
		}
200
	}
201
202
	/**
203
	 * Write the generated LocalSettings to a file
204
	 *
205
	 * @param string $fileName Full path to filename to write to
206
	 */
207
	public function writeFile( $fileName ) {
208
		file_put_contents( $fileName, $this->getText() );
209
	}
210
211
	/**
212
	 * @return string
213
	 */
214
	protected function buildMemcachedServerList() {
215
		$servers = $this->values['_MemCachedServers'];
216
217
		if ( !$servers ) {
218
			return '[]';
219
		} else {
220
			$ret = '[ ';
221
			$servers = explode( ',', $servers );
222
223
			foreach ( $servers as $srv ) {
224
				$srv = trim( $srv );
225
				$ret .= "'$srv', ";
226
			}
227
228
			return rtrim( $ret, ', ' ) . ' ]';
229
		}
230
	}
231
232
	/**
233
	 * @return string
234
	 */
235
	protected function getDefaultText() {
0 ignored issues
show
getDefaultText uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
236
		if ( !$this->values['wgImageMagickConvertCommand'] ) {
237
			$this->values['wgImageMagickConvertCommand'] = '/usr/bin/convert';
238
			$magic = '#';
239
		} else {
240
			$magic = '';
241
		}
242
243
		if ( !$this->values['wgShellLocale'] ) {
244
			$this->values['wgShellLocale'] = 'en_US.UTF-8';
245
			$locale = '#';
246
		} else {
247
			$locale = '';
248
		}
249
250
		$metaNamespace = '';
251
		if ( $this->values['wgMetaNamespace'] !== $this->values['wgSitename'] ) {
252
			$metaNamespace = "\$wgMetaNamespace = \"{$this->values['wgMetaNamespace']}\";\n";
253
		}
254
255
		$groupRights = '';
256
		$noFollow = '';
257
		if ( $this->groupPermissions ) {
258
			$groupRights .= "# The following permissions were set based on your choice in the installer\n";
259
			foreach ( $this->groupPermissions as $group => $rightArr ) {
260
				$group = self::escapePhpString( $group );
261
				foreach ( $rightArr as $right => $perm ) {
262
					$right = self::escapePhpString( $right );
263
					$groupRights .= "\$wgGroupPermissions['$group']['$right'] = " .
264
						wfBoolToStr( $perm ) . ";\n";
265
				}
266
			}
267
			$groupRights .= "\n";
268
269
			if ( ( isset( $this->groupPermissions['*']['edit'] ) &&
270
					$this->groupPermissions['*']['edit'] === false )
271
				&& ( isset( $this->groupPermissions['*']['createaccount'] ) &&
272
					$this->groupPermissions['*']['createaccount'] === false )
273
				&& ( isset( $this->groupPermissions['*']['read'] ) &&
274
					$this->groupPermissions['*']['read'] !== false )
275
			) {
276
				$noFollow = "# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
277
					. "# the general public and wish to apply nofollow to external links as a\n"
278
					. "# deterrent to spammers. Nofollow is not a comprehensive anti-spam solution\n"
279
					. "# and open wikis will generally require other anti-spam measures; for more\n"
280
					. "# information, see https://www.mediawiki.org/wiki/Manual:Combating_spam\n"
281
					. "\$wgNoFollowLinks = false;\n\n";
282
			}
283
		}
284
285
		$serverSetting = "";
286
		if ( array_key_exists( 'wgServer', $this->values ) && $this->values['wgServer'] !== null ) {
287
			$serverSetting = "\n## The protocol and server name to use in fully-qualified URLs\n";
288
			$serverSetting .= "\$wgServer = \"{$this->values['wgServer']}\";";
289
		}
290
291
		switch ( $this->values['_MainCacheType'] ) {
292
			case 'anything':
293
			case 'db':
294
			case 'memcached':
295
			case 'accel':
296
				$cacheType = 'CACHE_' . strtoupper( $this->values['_MainCacheType'] );
297
				break;
298
			case 'none':
299
			default:
300
				$cacheType = 'CACHE_NONE';
301
		}
302
303
		$mcservers = $this->buildMemcachedServerList();
304
305
		return "<?php
306
# This file was automatically generated by the MediaWiki {$GLOBALS['wgVersion']}
307
# installer. If you make manual changes, please keep track in case you
308
# need to recreate them later.
309
#
310
# See includes/DefaultSettings.php for all configurable settings
311
# and their default values, but don't forget to make changes in _this_
312
# file, not there.
313
#
314
# Further documentation for configuration settings may be found at:
315
# https://www.mediawiki.org/wiki/Manual:Configuration_settings
316
317
# Protect against web entry
318
if ( !defined( 'MEDIAWIKI' ) ) {
319
	exit;
320
}
321
322
## Uncomment this to disable output compression
323
# \$wgDisableOutputCompression = true;
324
325
\$wgSitename = \"{$this->values['wgSitename']}\";
326
{$metaNamespace}
327
## The URL base path to the directory containing the wiki;
328
## defaults for all runtime URL paths are based off of this.
329
## For more information on customizing the URLs
330
## (like /w/index.php/Page_title to /wiki/Page_title) please see:
331
## https://www.mediawiki.org/wiki/Manual:Short_URL
332
\$wgScriptPath = \"{$this->values['wgScriptPath']}\";
333
${serverSetting}
334
335
## The URL path to static resources (images, scripts, etc.)
336
\$wgResourceBasePath = \$wgScriptPath;
337
338
## The URL path to the logo.  Make sure you change this from the default,
339
## or else you'll overwrite your logo when you upgrade!
340
\$wgLogo = \"{$this->values['wgLogo']}\";
341
342
## UPO means: this is also a user preference option
343
344
\$wgEnableEmail = {$this->values['wgEnableEmail']};
345
\$wgEnableUserEmail = {$this->values['wgEnableUserEmail']}; # UPO
346
347
\$wgEmergencyContact = \"{$this->values['wgEmergencyContact']}\";
348
\$wgPasswordSender = \"{$this->values['wgPasswordSender']}\";
349
350
\$wgEnotifUserTalk = {$this->values['wgEnotifUserTalk']}; # UPO
351
\$wgEnotifWatchlist = {$this->values['wgEnotifWatchlist']}; # UPO
352
\$wgEmailAuthentication = {$this->values['wgEmailAuthentication']};
353
354
## Database settings
355
\$wgDBtype = \"{$this->values['wgDBtype']}\";
356
\$wgDBserver = \"{$this->values['wgDBserver']}\";
357
\$wgDBname = \"{$this->values['wgDBname']}\";
358
\$wgDBuser = \"{$this->values['wgDBuser']}\";
359
\$wgDBpassword = \"{$this->values['wgDBpassword']}\";
360
361
{$this->dbSettings}
362
363
## Shared memory settings
364
\$wgMainCacheType = $cacheType;
365
\$wgMemCachedServers = $mcservers;
366
367
## To enable image uploads, make sure the 'images' directory
368
## is writable, then set this to true:
369
\$wgEnableUploads = {$this->values['wgEnableUploads']};
370
{$magic}\$wgUseImageMagick = true;
371
{$magic}\$wgImageMagickConvertCommand = \"{$this->values['wgImageMagickConvertCommand']}\";
372
373
# InstantCommons allows wiki to use images from https://commons.wikimedia.org
374
\$wgUseInstantCommons = {$this->values['wgUseInstantCommons']};
375
376
# Periodically send a pingback to https://www.mediawiki.org/ with basic data
377
# about this MediaWiki instance. The Wikimedia Foundation shares this data
378
# with MediaWiki developers to help guide future development efforts.
379
\$wgPingback = {$this->values['wgPingback']};
380
381
## If you use ImageMagick (or any other shell command) on a
382
## Linux server, this will need to be set to the name of an
383
## available UTF-8 locale
384
{$locale}\$wgShellLocale = \"{$this->values['wgShellLocale']}\";
385
386
## Set \$wgCacheDirectory to a writable directory on the web server
387
## to make your wiki go slightly faster. The directory should not
388
## be publically accessible from the web.
389
#\$wgCacheDirectory = \"\$IP/cache\";
390
391
# Site language code, should be one of the list in ./languages/data/Names.php
392
\$wgLanguageCode = \"{$this->values['wgLanguageCode']}\";
393
394
\$wgSecretKey = \"{$this->values['wgSecretKey']}\";
395
396
# Changing this will log out all existing sessions.
397
\$wgAuthenticationTokenVersion = \"{$this->values['wgAuthenticationTokenVersion']}\";
398
399
# Site upgrade key. Must be set to a string (default provided) to turn on the
400
# web installer while LocalSettings.php is in place
401
\$wgUpgradeKey = \"{$this->values['wgUpgradeKey']}\";
402
403
## For attaching licensing metadata to pages, and displaying an
404
## appropriate copyright notice / icon. GNU Free Documentation
405
## License and Creative Commons licenses are supported so far.
406
\$wgRightsPage = \"\"; # Set to the title of a wiki page that describes your license/copyright
407
\$wgRightsUrl = \"{$this->values['wgRightsUrl']}\";
408
\$wgRightsText = \"{$this->values['wgRightsText']}\";
409
\$wgRightsIcon = \"{$this->values['wgRightsIcon']}\";
410
411
# Path to the GNU diff3 utility. Used for conflict resolution.
412
\$wgDiff3 = \"{$this->values['wgDiff3']}\";
413
414
{$groupRights}{$noFollow}## Default skin: you can change the default skin. Use the internal symbolic
415
## names, ie 'vector', 'monobook':
416
\$wgDefaultSkin = \"{$this->values['wgDefaultSkin']}\";
417
";
418
	}
419
}
420