LocalSettingsGenerator.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  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. * Class for generating LocalSettings.php file.
  25. *
  26. * @ingroup Deployment
  27. * @since 1.17
  28. */
  29. class LocalSettingsGenerator {
  30. protected $extensions = [];
  31. protected $skins = [];
  32. protected $values = [];
  33. protected $groupPermissions = [];
  34. protected $dbSettings = '';
  35. protected $IP;
  36. /**
  37. * @var Installer
  38. */
  39. protected $installer;
  40. /**
  41. * @param Installer $installer
  42. */
  43. public function __construct( Installer $installer ) {
  44. $this->installer = $installer;
  45. $this->extensions = $installer->getVar( '_Extensions' );
  46. $this->skins = $installer->getVar( '_Skins' );
  47. $this->IP = $installer->getVar( 'IP' );
  48. $db = $installer->getDBInstaller( $installer->getVar( 'wgDBtype' ) );
  49. $confItems = array_merge(
  50. [
  51. 'wgServer', 'wgScriptPath',
  52. 'wgPasswordSender', 'wgImageMagickConvertCommand', 'wgShellLocale',
  53. 'wgLanguageCode', 'wgEnableEmail', 'wgEnableUserEmail', 'wgDiff3',
  54. 'wgEnotifUserTalk', 'wgEnotifWatchlist', 'wgEmailAuthentication',
  55. 'wgDBtype', 'wgSecretKey', 'wgRightsUrl', 'wgSitename', 'wgRightsIcon',
  56. 'wgRightsText', '_MainCacheType', 'wgEnableUploads',
  57. '_MemCachedServers', 'wgDBserver', 'wgDBuser',
  58. 'wgDBpassword', 'wgUseInstantCommons', 'wgUpgradeKey', 'wgDefaultSkin',
  59. 'wgMetaNamespace', 'wgLogo', 'wgAuthenticationTokenVersion', 'wgPingback',
  60. ],
  61. $db->getGlobalNames()
  62. );
  63. $unescaped = [ 'wgRightsIcon', 'wgLogo', '_Caches' ];
  64. $boolItems = [
  65. 'wgEnableEmail', 'wgEnableUserEmail', 'wgEnotifUserTalk',
  66. 'wgEnotifWatchlist', 'wgEmailAuthentication', 'wgEnableUploads', 'wgUseInstantCommons',
  67. 'wgPingback',
  68. ];
  69. foreach ( $confItems as $c ) {
  70. $val = $installer->getVar( $c );
  71. if ( in_array( $c, $boolItems ) ) {
  72. $val = wfBoolToStr( $val );
  73. }
  74. if ( !in_array( $c, $unescaped ) && $val !== null ) {
  75. $val = self::escapePhpString( $val );
  76. }
  77. $this->values[$c] = $val;
  78. }
  79. $this->dbSettings = $db->getLocalSettings();
  80. $this->values['wgEmergencyContact'] = $this->values['wgPasswordSender'];
  81. }
  82. /**
  83. * For $wgGroupPermissions, set a given ['group']['permission'] value.
  84. * @param string $group Group name
  85. * @param array $rightsArr An array of permissions, in the form of:
  86. * [ 'right' => true, 'right2' => false ]
  87. */
  88. public function setGroupRights( $group, $rightsArr ) {
  89. $this->groupPermissions[$group] = $rightsArr;
  90. }
  91. /**
  92. * Returns the escaped version of a string of php code.
  93. *
  94. * @param string $string
  95. *
  96. * @return string|false
  97. */
  98. public static function escapePhpString( $string ) {
  99. if ( is_array( $string ) || is_object( $string ) ) {
  100. return false;
  101. }
  102. return strtr(
  103. $string,
  104. [
  105. "\n" => "\\n",
  106. "\r" => "\\r",
  107. "\t" => "\\t",
  108. "\\" => "\\\\",
  109. "\$" => "\\\$",
  110. "\"" => "\\\""
  111. ]
  112. );
  113. }
  114. /**
  115. * Return the full text of the generated LocalSettings.php file,
  116. * including the extensions and skins.
  117. *
  118. * @return string
  119. */
  120. public function getText() {
  121. $localSettings = $this->getDefaultText();
  122. if ( count( $this->skins ) ) {
  123. $localSettings .= "
  124. # Enabled skins.
  125. # The following skins were automatically enabled:\n";
  126. foreach ( $this->skins as $skinName ) {
  127. $localSettings .= $this->generateExtEnableLine( 'skins', $skinName );
  128. }
  129. $localSettings .= "\n";
  130. }
  131. if ( count( $this->extensions ) ) {
  132. $localSettings .= "
  133. # Enabled extensions. Most of the extensions are enabled by adding
  134. # wfLoadExtensions('ExtensionName');
  135. # to LocalSettings.php. Check specific extension documentation for more details.
  136. # The following extensions were automatically enabled:\n";
  137. foreach ( $this->extensions as $extName ) {
  138. $localSettings .= $this->generateExtEnableLine( 'extensions', $extName );
  139. }
  140. $localSettings .= "\n";
  141. }
  142. $localSettings .= "
  143. # End of automatically generated settings.
  144. # Add more configuration options below.\n\n";
  145. return $localSettings;
  146. }
  147. /**
  148. * Generate the appropriate line to enable the given extension or skin
  149. *
  150. * @param string $dir Either "extensions" or "skins"
  151. * @param string $name Name of extension/skin
  152. * @throws InvalidArgumentException
  153. * @return string
  154. */
  155. private function generateExtEnableLine( $dir, $name ) {
  156. if ( $dir === 'extensions' ) {
  157. $jsonFile = 'extension.json';
  158. $function = 'wfLoadExtension';
  159. } elseif ( $dir === 'skins' ) {
  160. $jsonFile = 'skin.json';
  161. $function = 'wfLoadSkin';
  162. } else {
  163. throw new InvalidArgumentException( '$dir was not "extensions" or "skins"' );
  164. }
  165. $encName = self::escapePhpString( $name );
  166. if ( file_exists( "{$this->IP}/$dir/$encName/$jsonFile" ) ) {
  167. return "$function( '$encName' );\n";
  168. } else {
  169. return "require_once \"\$IP/$dir/$encName/$encName.php\";\n";
  170. }
  171. }
  172. /**
  173. * Write the generated LocalSettings to a file
  174. *
  175. * @param string $fileName Full path to filename to write to
  176. */
  177. public function writeFile( $fileName ) {
  178. file_put_contents( $fileName, $this->getText() );
  179. }
  180. /**
  181. * @return string
  182. */
  183. protected function buildMemcachedServerList() {
  184. $servers = $this->values['_MemCachedServers'];
  185. if ( !$servers ) {
  186. return '[]';
  187. } else {
  188. $ret = '[ ';
  189. $servers = explode( ',', $servers );
  190. foreach ( $servers as $srv ) {
  191. $srv = trim( $srv );
  192. $ret .= "'$srv', ";
  193. }
  194. return rtrim( $ret, ', ' ) . ' ]';
  195. }
  196. }
  197. /**
  198. * @return string
  199. */
  200. protected function getDefaultText() {
  201. if ( !$this->values['wgImageMagickConvertCommand'] ) {
  202. $this->values['wgImageMagickConvertCommand'] = '/usr/bin/convert';
  203. $magic = '#';
  204. } else {
  205. $magic = '';
  206. }
  207. if ( !$this->values['wgShellLocale'] ) {
  208. $this->values['wgShellLocale'] = 'C.UTF-8';
  209. $locale = '#';
  210. } else {
  211. $locale = '';
  212. }
  213. $metaNamespace = '';
  214. if ( $this->values['wgMetaNamespace'] !== $this->values['wgSitename'] ) {
  215. $metaNamespace = "\$wgMetaNamespace = \"{$this->values['wgMetaNamespace']}\";\n";
  216. }
  217. $groupRights = '';
  218. $noFollow = '';
  219. if ( $this->groupPermissions ) {
  220. $groupRights .= "# The following permissions were set based on your choice in the installer\n";
  221. foreach ( $this->groupPermissions as $group => $rightArr ) {
  222. $group = self::escapePhpString( $group );
  223. foreach ( $rightArr as $right => $perm ) {
  224. $right = self::escapePhpString( $right );
  225. $groupRights .= "\$wgGroupPermissions['$group']['$right'] = " .
  226. wfBoolToStr( $perm ) . ";\n";
  227. }
  228. }
  229. $groupRights .= "\n";
  230. if ( ( isset( $this->groupPermissions['*']['edit'] ) &&
  231. $this->groupPermissions['*']['edit'] === false )
  232. && ( isset( $this->groupPermissions['*']['createaccount'] ) &&
  233. $this->groupPermissions['*']['createaccount'] === false )
  234. && ( isset( $this->groupPermissions['*']['read'] ) &&
  235. $this->groupPermissions['*']['read'] !== false )
  236. ) {
  237. $noFollow = "# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
  238. . "# the general public and wish to apply nofollow to external links as a\n"
  239. . "# deterrent to spammers. Nofollow is not a comprehensive anti-spam solution\n"
  240. . "# and open wikis will generally require other anti-spam measures; for more\n"
  241. . "# information, see https://www.mediawiki.org/wiki/Manual:Combating_spam\n"
  242. . "\$wgNoFollowLinks = false;\n\n";
  243. }
  244. }
  245. $serverSetting = "";
  246. if ( array_key_exists( 'wgServer', $this->values ) && $this->values['wgServer'] !== null ) {
  247. $serverSetting = "\n## The protocol and server name to use in fully-qualified URLs\n";
  248. $serverSetting .= "\$wgServer = \"{$this->values['wgServer']}\";";
  249. }
  250. switch ( $this->values['_MainCacheType'] ) {
  251. case 'anything':
  252. case 'db':
  253. case 'memcached':
  254. case 'accel':
  255. $cacheType = 'CACHE_' . strtoupper( $this->values['_MainCacheType'] );
  256. break;
  257. case 'none':
  258. default:
  259. $cacheType = 'CACHE_NONE';
  260. }
  261. $mcservers = $this->buildMemcachedServerList();
  262. if ( file_exists( dirname( __DIR__ ) . '/PlatformSettings.php' ) ) {
  263. $platformSettings = "\n## Include platform/distribution defaults";
  264. $platformSettings .= "\nrequire_once \"\$IP/includes/PlatformSettings.php\";";
  265. } else {
  266. $platformSettings = '';
  267. }
  268. return "<?php
  269. # This file was automatically generated by the MediaWiki {$GLOBALS['wgVersion']}
  270. # installer. If you make manual changes, please keep track in case you
  271. # need to recreate them later.
  272. #
  273. # See includes/DefaultSettings.php for all configurable settings
  274. # and their default values, but don't forget to make changes in _this_
  275. # file, not there.
  276. #
  277. # Further documentation for configuration settings may be found at:
  278. # https://www.mediawiki.org/wiki/Manual:Configuration_settings
  279. # Protect against web entry
  280. if ( !defined( 'MEDIAWIKI' ) ) {
  281. exit;
  282. }
  283. {$platformSettings}
  284. ## Uncomment this to disable output compression
  285. # \$wgDisableOutputCompression = true;
  286. \$wgSitename = \"{$this->values['wgSitename']}\";
  287. {$metaNamespace}
  288. ## The URL base path to the directory containing the wiki;
  289. ## defaults for all runtime URL paths are based off of this.
  290. ## For more information on customizing the URLs
  291. ## (like /w/index.php/Page_title to /wiki/Page_title) please see:
  292. ## https://www.mediawiki.org/wiki/Manual:Short_URL
  293. \$wgScriptPath = \"{$this->values['wgScriptPath']}\";
  294. ${serverSetting}
  295. ## The URL path to static resources (images, scripts, etc.)
  296. \$wgResourceBasePath = \$wgScriptPath;
  297. ## The URL path to the logo. Make sure you change this from the default,
  298. ## or else you'll overwrite your logo when you upgrade!
  299. \$wgLogo = \"{$this->values['wgLogo']}\";
  300. ## UPO means: this is also a user preference option
  301. \$wgEnableEmail = {$this->values['wgEnableEmail']};
  302. \$wgEnableUserEmail = {$this->values['wgEnableUserEmail']}; # UPO
  303. \$wgEmergencyContact = \"{$this->values['wgEmergencyContact']}\";
  304. \$wgPasswordSender = \"{$this->values['wgPasswordSender']}\";
  305. \$wgEnotifUserTalk = {$this->values['wgEnotifUserTalk']}; # UPO
  306. \$wgEnotifWatchlist = {$this->values['wgEnotifWatchlist']}; # UPO
  307. \$wgEmailAuthentication = {$this->values['wgEmailAuthentication']};
  308. ## Database settings
  309. \$wgDBtype = \"{$this->values['wgDBtype']}\";
  310. \$wgDBserver = \"{$this->values['wgDBserver']}\";
  311. \$wgDBname = \"{$this->values['wgDBname']}\";
  312. \$wgDBuser = \"{$this->values['wgDBuser']}\";
  313. \$wgDBpassword = \"{$this->values['wgDBpassword']}\";
  314. {$this->dbSettings}
  315. ## Shared memory settings
  316. \$wgMainCacheType = $cacheType;
  317. \$wgMemCachedServers = $mcservers;
  318. ## To enable image uploads, make sure the 'images' directory
  319. ## is writable, then set this to true:
  320. \$wgEnableUploads = {$this->values['wgEnableUploads']};
  321. {$magic}\$wgUseImageMagick = true;
  322. {$magic}\$wgImageMagickConvertCommand = \"{$this->values['wgImageMagickConvertCommand']}\";
  323. # InstantCommons allows wiki to use images from https://commons.wikimedia.org
  324. \$wgUseInstantCommons = {$this->values['wgUseInstantCommons']};
  325. # Periodically send a pingback to https://www.mediawiki.org/ with basic data
  326. # about this MediaWiki instance. The Wikimedia Foundation shares this data
  327. # with MediaWiki developers to help guide future development efforts.
  328. \$wgPingback = {$this->values['wgPingback']};
  329. ## If you use ImageMagick (or any other shell command) on a
  330. ## Linux server, this will need to be set to the name of an
  331. ## available UTF-8 locale
  332. {$locale}\$wgShellLocale = \"{$this->values['wgShellLocale']}\";
  333. ## Set \$wgCacheDirectory to a writable directory on the web server
  334. ## to make your wiki go slightly faster. The directory should not
  335. ## be publicly accessible from the web.
  336. #\$wgCacheDirectory = \"\$IP/cache\";
  337. # Site language code, should be one of the list in ./languages/data/Names.php
  338. \$wgLanguageCode = \"{$this->values['wgLanguageCode']}\";
  339. \$wgSecretKey = \"{$this->values['wgSecretKey']}\";
  340. # Changing this will log out all existing sessions.
  341. \$wgAuthenticationTokenVersion = \"{$this->values['wgAuthenticationTokenVersion']}\";
  342. # Site upgrade key. Must be set to a string (default provided) to turn on the
  343. # web installer while LocalSettings.php is in place
  344. \$wgUpgradeKey = \"{$this->values['wgUpgradeKey']}\";
  345. ## For attaching licensing metadata to pages, and displaying an
  346. ## appropriate copyright notice / icon. GNU Free Documentation
  347. ## License and Creative Commons licenses are supported so far.
  348. \$wgRightsPage = \"\"; # Set to the title of a wiki page that describes your license/copyright
  349. \$wgRightsUrl = \"{$this->values['wgRightsUrl']}\";
  350. \$wgRightsText = \"{$this->values['wgRightsText']}\";
  351. \$wgRightsIcon = \"{$this->values['wgRightsIcon']}\";
  352. # Path to the GNU diff3 utility. Used for conflict resolution.
  353. \$wgDiff3 = \"{$this->values['wgDiff3']}\";
  354. {$groupRights}{$noFollow}## Default skin: you can change the default skin. Use the internal symbolic
  355. ## names, ie 'vector', 'monobook':
  356. \$wgDefaultSkin = \"{$this->values['wgDefaultSkin']}\";
  357. ";
  358. }
  359. }