Seb35 has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/355633 )

Change subject: Refactoring: extraction of configuration compilation
......................................................................

Refactoring: extraction of configuration compilation

The main class MediaWikiFarm had a lot of responsabilities, one of those was
to compile configuration for a specific wiki. This commits splits out this
configuration compilation into a dedicated class. In number of lines, the
main class MediaWikiFarm drops from 2030 to 1427.

This is a first step to more refactoring to create smaller functions and
possibly multiple classes, in order to facilitate long-term maintenance and
improve understanding. Possibly the 'existence' feature inside the main
class will be also splitted out into a dedicated class, which would become
sort of a (dependency injection) container.

Change-Id: I54d4d2739215f9cc4f59fb2671d2cd7e797d16f9
---
M extension.json
M src/MediaWikiFarm.php
M src/MediaWikiFarmComposerScript.php
A src/MediaWikiFarmConfiguration.php
M tests/perfs/MediaWikiFarmTestPerfs.php
M tests/phpunit/ConfigurationTest.php
M tests/phpunit/ConstructionTest.php
M tests/phpunit/InstallationIndependantTest.php
M tests/phpunit/LoadingTest.php
M tests/phpunit/MediaWikiFarmComposerScriptTest.php
M tests/phpunit/MediaWikiFarmScriptTest.php
11 files changed, 1,038 insertions(+), 784 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MediaWikiFarm 
refs/changes/33/355633/1

diff --git a/extension.json b/extension.json
index 0526ebb..5bd8da9 100644
--- a/extension.json
+++ b/extension.json
@@ -29,6 +29,7 @@
        },
        "AutoloadClasses": {
                "MediaWikiFarm": "src/MediaWikiFarm.php",
+               "MediaWikiFarmConfiguration": 
"src/MediaWikiFarmConfiguration.php",
                "AbstractMediaWikiFarmScript": 
"src/AbstractMediaWikiFarmScript.php",
                "MediaWikiFarmScript": "src/MediaWikiFarmScript.php",
                "MediaWikiFarmHooks": "src/Hooks.php",
diff --git a/src/MediaWikiFarm.php b/src/MediaWikiFarm.php
index 6705369..f269008 100644
--- a/src/MediaWikiFarm.php
+++ b/src/MediaWikiFarm.php
@@ -11,6 +11,10 @@
  *             PHP 5.2+, so please do not use "new" syntaxes (namespaces, 
arrays with [], etc.).
  */
 
+// @codeCoverageIgnoreStart
+require_once dirname( __FILE__ ) . '/MediaWikiFarmConfiguration.php';
+// @codeCoverageIgnoreEnd
+
 /**
  * Exception triggered when a configuration file is “wrong” or other internal 
issue.
  *
@@ -74,19 +78,8 @@
                '$CODE' => '',
        );
 
-       /** @var array Environment. */
-       protected $environment = array(
-               'ExtensionRegistry' => null,
-       );
-
-       /** @var array Configuration parameters for this wiki. */
-       protected $configuration = array(
-               'settings' => array(),
-               'arrays' => array(),
-               'extensions' => array(),
-               'execFiles' => array(),
-               'composer' => array(),
-       );
+       /** @var MediaWikiFarmConfiguration|null Object containing the 
configuration of the current (single) wiki. */
+       protected $configuration = null;
 
        /** @var array Logs. */
        public $log = array();
@@ -110,6 +103,32 @@
                        return $this->state[$key];
                }
                return null;
+       }
+
+       /**
+        * Get farm this farm code directory.
+        *
+        * @api
+        * @mediawikifarm-const
+        * @mediawikifarm-idempotent
+        *
+        * @return string|null Farm code directory.
+        */
+       function getFarmDir() {
+               return $this->farmDir;
+       }
+
+       /**
+        * Get config directory.
+        *
+        * @api
+        * @mediawikifarm-const
+        * @mediawikifarm-idempotent
+        *
+        * @return string|null Config directory.
+        */
+       function getConfigDir() {
+               return $this->configDir;
        }
 
        /**
@@ -198,23 +217,19 @@
         * @api
         * @mediawikifarm-const
         *
-        * @param string|null $key Key of the wanted section or null for the 
whole array.
-        * @param string|null $key2 Subkey (specific to each entry) or null for 
the whole entry.
-        * @return array MediaWiki configuration, either entire, either a part 
depending on the parameter.
+        * @param string|false|null $key Key of the wanted section or false for 
the whole array or null for the object configuration.
+        * @param string|false $key2 Subkey (specific to each entry) or false 
for the whole entry.
+        * @return array|MediaWikiFarmConfiguration MediaWiki configuration, 
either entire, either a part depending on the parameter, or the configuration 
object.
         */
-       function getConfiguration( $key = null, $key2 = null ) {
-               if( $key !== null ) {
-                       if( array_key_exists( $key, $this->configuration ) ) {
-                               if( $key2 !== null && array_key_exists( $key2, 
$this->configuration[$key] ) ) {
-                                       return 
$this->configuration[$key][$key2];
-                               } elseif( $key2 !== null ) {
-                                       return null;
-                               }
-                               return $this->configuration[$key];
-                       }
-                       return null;
+       function getConfiguration( $key = false, $key2 = false ) {
+               if( $this->configuration === null ) {
+                       $that =& $this;
+                       $this->configuration = new MediaWikiFarmConfiguration( 
$that );
                }
-               return $this->configuration;
+               if( $key === null ) {
+                       return $this->configuration;
+               }
+               return $this->configuration->getConfiguration( $key, $key2 );
        }
 
 
@@ -380,25 +395,35 @@
 
                        $composerFile = $this->readFile( 
$this->variables['$SERVER'] . '.php', $this->cacheDir . '/composer', false );
                        if( is_array( $composerFile ) ) {
-                               $this->configuration['composer'] = 
$composerFile;
+                               if( $this->configuration === null ) {
+                                       $that =& $this;
+                                       $this->configuration = new 
MediaWikiFarmConfiguration( $that );
+                               }
+                               $this->configuration->setComposer( 
$composerFile );
                        }
 
                        return;
                }
 
+               # Init configuration object
+               if( $this->configuration === null ) {
+                       $that =& $this;
+                       $this->configuration = new MediaWikiFarmConfiguration( 
$that );
+               }
+
                # Transform configuration files to a unique configuration
-               if( count( $this->configuration['settings'] ) == 0 ) {
+               if( count( $this->getConfiguration( 'settings' ) ) == 0 ) {
 
                        # Compile the configuration
-                       $this->populateSettings();
+                       $this->configuration->populateSettings();
 
                        # Activate the extensions (possibly not finished here
                        # if we do not know the entire MediaWiki environment)
-                       $this->activateExtensions();
+                       $this->configuration->activateExtensions();
 
                        # Save Composer key if available
                        if( $this->cacheDir && !array_key_exists( 
'unreadable-file', $this->log ) ) {
-                               self::cacheFile( 
$this->configuration['composer'],
+                               self::cacheFile( $this->getConfiguration( 
'composer' ),
                                        $this->variables['$SERVER'] . '.php',
                                        $this->cacheDir . '/composer'
                                );
@@ -406,14 +431,17 @@
                }
 
                # When the MediaWiki environment is set
-               if( $this->setEnvironment() ) {
+               if( $this->state['InnerMediaWiki'] ) {
+
+                       # Set environment
+                       $this->configuration->setEnvironment();
 
                        # Finalise the extension activation
-                       $this->activateExtensions();
+                       $this->configuration->activateExtensions();
 
                        # Create the final LocalSettings.php
                        if( $this->cacheDir && !array_key_exists( 
'unreadable-file', $this->log ) ) {
-                               self::cacheFile( $this->createLocalSettings( 
$this->configuration ),
+                               self::cacheFile( 
MediaWikiFarmConfiguration::createLocalSettings( $this->getConfiguration(), 
(bool) $this->codeDir ),
                                        $this->variables['$SERVER'] . '.php',
                                        $this->cacheDir . '/LocalSettings'
                                );
@@ -448,13 +476,13 @@
        function loadMediaWikiConfig() {
 
                # Set general parameters as global variables
-               foreach( $this->configuration['settings'] as $setting => $value 
) {
+               foreach( $this->getConfiguration( 'settings' ) as $setting => 
$value ) {
 
                        $GLOBALS[$setting] = $value;
                }
 
                # Merge general array parameters into global variables
-               foreach( $this->configuration['arrays'] as $setting => $value ) 
{
+               foreach( $this->getConfiguration( 'arrays' ) as $setting => 
$value ) {
 
                        if( !array_key_exists( $setting, $GLOBALS ) ) {
                                $GLOBALS[$setting] = array();
@@ -463,7 +491,7 @@
                }
 
                # Load extensions and skins with the wfLoadExtension/wfLoadSkin 
mechanism
-               foreach( $this->configuration['extensions'] as $key => 
$extension ) {
+               foreach( $this->getConfiguration( 'extensions' ) as $key => 
$extension ) {
 
                        if( $extension[2] == 'wfLoadExtension' ) {
 
@@ -480,8 +508,8 @@
                }
 
                # Register this extension MediaWikiFarm to appear in 
Special:Version
-               if( array_key_exists( 'ExtensionMediaWikiFarm', 
$this->configuration['extensions'] ) &&
-                    
$this->configuration['extensions']['ExtensionMediaWikiFarm'][2] == 
'require_once' &&
+               if( array_key_exists( 'ExtensionMediaWikiFarm', 
$this->getConfiguration( 'extensions' ) ) &&
+                    $this->getConfiguration( 'extensions', 
'ExtensionMediaWikiFarm' )[2] == 'require_once' &&
                     $this->codeDir ) {
                        $GLOBALS['wgExtensionCredits']['other'][] = array(
                                'path' => $this->farmDir . '/MediaWikiFarm.php',
@@ -702,9 +730,15 @@
                        'EntryPoint' => '',
                        'InnerMediaWiki' => null,
                ), $state );
-               $this->environment = array_merge( array(
-                       'ExtensionRegistry' => null,
-               ), $environment );
+               if( $environment ) {
+                       $environment = array_merge( array(
+                               'ExtensionRegistry' => null,
+                       ), $environment );
+
+                       $that =& $this;
+                       $this->configuration = new MediaWikiFarmConfiguration( 
$that );
+                       $this->configuration->setEnvironment( 
'ExtensionRegistry', $environment['ExtensionRegistry'] );
+               }
 
                # Shortcut loading
                // @codingStandardsIgnoreLine
@@ -1084,587 +1118,6 @@
        }
 
        /**
-        * Popuplate the settings array directly from config files (without 
wgConf).
-        *
-        * There should be no major differences is results between this 
function and results
-        * of SiteConfiguration::getAll(), but probably some edge cases. At the 
contrary of
-        * Siteconfiguration, this implementation is focused on performance for 
current wiki:
-        * only the parameters for current wikis are issued, contrary to 
wgConf’s strategy
-        * map-all-and-reduce. An additional loop over config files is here; 
wgConf delegates
-        * this externally if wanted.
-        *
-        * The priories used here are implicit in wgConf but exist and behave 
similarly:
-        * 0 = default value from MW; 1 = explicit very default value from a 
specific file;
-        * 2 = standard default value; 3 = value with suffix-priority;
-        * 4 = value with tag-priority; 5 = value with specific-wiki-priority. 
Files are
-        * processed in-order and linearly; for a given setting, only values 
with a greater
-        * or equal priority can override a previous value.
-        *
-        * There are two resulting arrays in the object property array 
'configuration':
-        *   - settings: scalar (or array) values overriding the default MW 
values;
-        *   - arrays: array values merged into the default MW values.
-        * They are processed differently given their different nature, and to 
facilitate
-        * mass-import into global scope (or other configuration object). 
Another minor
-        * reason is: if this processing is done on a MediaWiki installation in 
a version
-        * different from the target version (sort of cross-compilation), the 
compiling
-        * MW is not aware of the default array value of the target MW, so it is
-        * safer to only manipulate the known difference.
-        *
-        * @internal
-        * @SuppressWarnings(PHPMD.ElseExpression)
-        * @SuppressWarnings(PHPMD.CyclomaticComplexity)
-        *
-        * @return bool Success.
-        */
-       function populateSettings() {
-
-               $settings = &$this->configuration['settings'];
-               $priorities = array();
-               $settingsArray = &$this->configuration['arrays'];
-               $prioritiesArray = array();
-
-               $extensions =& $this->configuration['extensions'];
-
-               $settings['wgUseExtensionMediaWikiFarm'] = true;
-               $extensions['ExtensionMediaWikiFarm'] = array( 'MediaWikiFarm', 
'extension', null, 0 );
-
-               foreach( $this->farmConfig['config'] as $configFile ) {
-
-                       if( !is_array( $configFile ) ) {
-                               continue;
-                       }
-
-                       # Replace variables
-                       $configFile = $this->replaceVariables( $configFile );
-
-                       # Executable config files
-                       if( array_key_exists( 'executable', $configFile ) && 
$configFile['executable'] ) {
-
-                               $this->configuration['execFiles'][] = 
$this->configDir . '/' . $configFile['file'];
-                               continue;
-                       }
-
-                       $theseSettings = $this->readFile( $configFile['file'], 
$this->configDir );
-                       if( $theseSettings === false ) {
-                               # If a file is unavailable, skip it
-                               continue;
-                       }
-
-                       # Defined key
-                       if( strpos( $configFile['key'], '*' ) === false ) {
-
-                               $priority = 0;
-                               if( $configFile['key'] == 'default' ) {
-                                       $priority = 1;
-                               } elseif( $configFile['key'] == 
$this->variables['$SUFFIX'] ) {
-                                       $priority = 3;
-                               } elseif( $configFile['key'] == 
$this->variables['$WIKIID'] ) {
-                                       $priority = 5;
-                               } else {
-                                       /*foreach( $tags as $tag ) {
-                                               if( $configFile['key'] == $tag 
) {
-                                                       $priority = 4;
-                                                       break;
-                                               }
-                                       }*/
-                                       if( $priority == 0 ) {
-                                               continue;
-                                       }
-                               }
-
-                               foreach( $theseSettings as $rawSetting => 
$value ) {
-
-                                       # Sanitise the setting name
-                                       $setting = preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $rawSetting );
-
-                                       if( substr( $rawSetting, 0, 1 ) == '+' 
) {
-                                               if( !array_key_exists( 
$setting, $prioritiesArray ) || $prioritiesArray[$setting] <= $priority ) {
-                                                       
$settingsArray[$setting] = $value;
-                                                       
$prioritiesArray[$setting] = $priority;
-                                               }
-                                       }
-                                       elseif( !array_key_exists( $setting, 
$priorities ) || $priorities[$setting] <= $priority ) {
-                                               $settings[$setting] = $value;
-                                               $priorities[$setting] = 
$priority;
-                                               if( substr( $setting, 0, 14 ) 
== 'wgUseExtension' ) {
-                                                       $extensions['Extension' 
. substr( $rawSetting, 14 )] = array( substr( $rawSetting, 14 ), 'extension', 
null, count( $extensions ) );
-                                               } elseif( substr( $setting, 0, 
9 ) == 'wgUseSkin' ) {
-                                                       $extensions['Skin' . 
substr( $rawSetting, 9 )] = array( substr( $rawSetting, 9 ), 'skin', null, 
count( $extensions ) );
-                                               }
-                                       }
-                               }
-                       }
-
-                       # Regex key
-                       else {
-
-                               // $tags = array(); # @todo data sources not 
implemented, but code to selection parameters from a tag is below
-
-                               $defaultKey = '';
-                               $classicKey = '';
-                               if( array_key_exists( 'default', $configFile ) 
&& is_string( $configFile['default'] ) ) {
-                                       $defaultKey = $this->replaceVariables( 
$configFile['default'] );
-                               }
-                               if( is_string( $configFile['key'] ) ) {
-                                       $classicKey = $this->replaceVariables( 
$configFile['key'] );
-                               }
-
-                               # These are precomputations of the condition 
`$classicKey == $wikiID` (is current wiki equal to key indicated in config 
file?)
-                               # to avoid recompute it each time in the loop. 
This is a bit more complex to take into account the star: $wikiID is the part
-                               # corresponding to the star from the variable 
$WIKIID if $classicKey can match $WIKIID when remplacing the star by something
-                               # (the star will be the key in the files). This 
reasonning is “inversed” compared to a loop checking each key in the files
-                               # in order to use array_key_exists, assumed to 
be quicker than a direct loop.
-                               $wikiIDKey = (bool) preg_match( 
'/^'.str_replace( '*', '(.+)', $classicKey ).'$/', $this->variables['$WIKIID'], 
$matches );
-                               $wikiID = $wikiIDKey ? $matches[1] : 
$this->variables['$WIKIID'];
-                               $suffixKey = (bool) preg_match( 
'/^'.str_replace( '*', '(.+)', $classicKey ).'$/', $this->variables['$SUFFIX'], 
$matches );
-                               $suffix = $suffixKey ? $matches[1] : 
$this->variables['$SUFFIX'];
-                               /*$tagKey = array();
-                               foreach( $tags as $tag ) {
-                                       $tagKey[$tag] = ($classicKey == $tag);
-                               }*/
-                               if( $defaultKey ) {
-                                       $suffixDefaultKey = (bool) preg_match( 
'/^'.str_replace( '*', '(.+)', $defaultKey ).'$/', $this->variables['$SUFFIX'], 
$matches );
-                                       // $tagDefaultKey = in_array( 
$defaultKey, $tags );
-                               }
-
-                               foreach( $theseSettings as $rawSetting => 
$values ) {
-
-                                       # Sanitise the setting name
-                                       $setting = preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $rawSetting );
-
-                                       # Depending if it is an array diff or 
not, create and initialise the variables
-                                       if( substr( $rawSetting, 0, 1 ) == '+' 
) {
-                                               $settingIsArray = true;
-                                               if( !array_key_exists( 
$setting, $prioritiesArray ) ) {
-                                                       
$settingsArray[$setting] = array();
-                                                       
$prioritiesArray[$setting] = 0;
-                                               }
-                                               $thisSetting =  
&$settingsArray[$setting];
-                                               $thisPriority = 
&$prioritiesArray[$setting];
-                                       } else {
-                                               $settingIsArray = false;
-                                               if( !array_key_exists( 
$setting, $priorities ) ) {
-                                                       $settings[$setting] = 
null;
-                                                       $priorities[$setting] = 
0;
-                                               }
-                                               $thisSetting =  
&$settings[$setting];
-                                               $thisPriority = 
&$priorities[$setting];
-                                               if( substr( $setting, 0, 14 ) 
== 'wgUseExtension' ) {
-                                                       $extensions['Extension' 
. substr( $rawSetting, 14 )] = array( substr( $rawSetting, 14 ), 'extension', 
null, count( $extensions ) );
-                                               } elseif( substr( $setting, 0, 
9 ) == 'wgUseSkin' ) {
-                                                       $extensions['Skin' . 
substr( $rawSetting, 9 )] = array( substr( $rawSetting, 9 ), 'skin', null, 
count( $extensions ) );
-                                               }
-                                       }
-
-                                       # Set value if there is a label 
corresponding to wikiID
-                                       if( $wikiIDKey ) {
-                                               if( array_key_exists( $wikiID, 
$values ) ) {
-                                                       $thisSetting = 
$values[$wikiID];
-                                                       $thisPriority = 5;
-                                                       continue;
-                                               }
-                                               if( array_key_exists( 
'+'.$wikiID, $values ) && is_array( $values['+'.$wikiID] ) ) {
-                                                       $thisSetting = 
self::arrayMerge( $thisSetting, $values['+'.$wikiID] );
-                                                       $thisPriority = 3;
-                                               }
-                                       }
-
-                                       # Set value if there are labels 
corresponding to given tags
-                                       /*$setted = false;
-                                       foreach( $tags as $tag ) {
-                                               if( $tagKey[$tag] && 
$thisPriority <= 4 ) {
-                                                       if( array_key_exists( 
$tag, $values ) ) {
-                                                               $thisSetting = 
$value[$tag];
-                                                               $thisPriority = 
4;
-                                                               $setted = true;
-                                                               # NB: for 
strict equivalence with wgConf there should be here a `break`, but by 
consistency
-                                                               # (last value 
kept) and given the case should not appear, there is no.
-                                                       }
-                                                       elseif( 
array_key_exists( '+'.$tag, $values ) && is_array( $values['+'.$tag] ) ) {
-                                                               $thisSetting = 
self::arrayMerge( $thisSetting, $values['+'.$tag] );
-                                                               $thisPriority = 
3;
-                                                       }
-                                               }
-                                       }
-                                       if( $setted ) {
-                                               continue;
-                                       }*/
-
-                                       # Set value if there is a label 
corresponding to suffix
-                                       if( $suffixKey && $thisPriority <= 3 ) {
-                                               if( array_key_exists( $suffix, 
$values ) ) {
-                                                       $thisSetting = 
$values[$suffix];
-                                                       $thisPriority = 3;
-                                                       continue;
-                                               }
-                                               if( array_key_exists( 
'+'.$suffix, $values ) && is_array( $values['+'.$suffix] ) ) {
-                                                       $thisSetting = 
self::arrayMerge( $thisSetting, $values['+'.$suffix] );
-                                                       $thisPriority = 3;
-                                               }
-                                       }
-
-                                       # Default value
-                                       if( $thisPriority <= 2 && 
array_key_exists( 'default', $values ) ) {
-                                               $thisSetting = 
$values['default'];
-                                               $thisPriority = 2;
-                                               if( $defaultKey ) {
-                                                       if( $suffixDefaultKey ) 
{
-                                                               $thisPriority = 
3;
-                                                       /*} elseif( 
$tagDefaultKey ) {
-                                                               $thisPriority = 
4;*/
-                                                       }
-                                               }
-                                               continue;
-                                       }
-
-                                       # Nothing was selected, clean up
-                                       if( $thisPriority == 0 ) {
-                                               if( $settingIsArray ) {
-                                                       unset( 
$settingsArray[$setting] );
-                                                       unset( 
$prioritiesArray[$setting] );
-                                               } else {
-                                                       unset( 
$settings[$setting] );
-                                                       unset( 
$priorities[$setting] );
-                                                       if( substr( $setting, 
0, 14 ) == 'wgUseExtension' ) {
-                                                               unset( 
$extensions['Extension' . substr( $rawSetting, 14 )] );
-                                                       } elseif( substr( 
$setting, 0, 9 ) == 'wgUseSkin' ) {
-                                                               unset( 
$extensions['Skin' . substr( $rawSetting, 9 )] );
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               return true;
-       }
-
-       /**
-        * Set environment, i.e. every 'environment variables' which lead to a 
known configuration.
-        *
-        * For now, the only environment variable is ExtensionRegistry (is the 
MediaWiki version
-        * capable of loading extensions/skins with 
wfLoadExtension/wfLoadSkin?).
-        *
-        * @internal
-        *
-        * @return void
-        */
-       function setEnvironment() {
-
-               if( !$this->state['InnerMediaWiki'] ) {
-                       return false;
-               }
-
-               # Set environment
-               $this->environment['ExtensionRegistry'] = class_exists( 
'ExtensionRegistry' );
-
-               return true;
-       }
-
-       /**
-        * Activate extensions and skins depending on their autoloading and 
activation mechanisms.
-        *
-        * When the environment parameter ExtensionRegistry is not set (null), 
only Composer-enabled
-        * extensions and skins are Composer-autoloaded; and if 
ExtensionRegistry is set to true or
-        * false, extensions and skins are activated through 
wfLoadExtension/wfLoadSkin or require_once.
-        *
-        * The part related to Composer is a bit complicated (partly since 
optimised): when an extension
-        * is Composer-managed, it is checked if it was already loaded by 
another extension (in which
-        * case Composer has autoloaded its code), then it is registered as 
Composer-managed, then its
-        * required extensions are registered. This last part is important, 
else Composer would have
-        * silently autoloaded the required extensions, but these would not be 
known by MediaWikiFarm
-        * and, more importantly, an eventual wfLoadExtension would not be 
triggered (e.g. PageForms 4.0+
-        * is a Composer dependency of the Composer-installed 
SemanticFormsSelect; if you activate SFS
-        * but not PF, PF would not be wfLoadExtension’ed – since unknown from 
MediaWikiFarm – and the
-        * wfLoadExtension’s SFS issues a fatal error since PF is not 
wfLoadExtension’ed, even if it is
-        * Composer-installed).
-        *
-        * @internal
-        *
-        * @return void
-        */
-       function activateExtensions() {
-
-               # Autodetect if ExtensionRegistry is here
-               $ExtensionRegistry = $this->environment['ExtensionRegistry'];
-
-               # Load Composer dependencies if available
-               $composerLoaded = array();
-               $dependencies = $this->readFile( 'MediaWikiExtensions.php', 
$this->variables['$CODE'] . '/vendor', false );
-               if( !$dependencies ) {
-                       $dependencies = array();
-               }
-
-               # Search for skin and extension activation
-               foreach( $this->configuration['extensions'] as $key => 
&$extension ) {
-
-                       $type = $extension[1];
-                       $name = $extension[0];
-                       $status =& $extension[2];
-
-                       $setting = 'wgUse' . preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $key );
-                       $value =& $this->configuration['settings'][$setting];
-
-                       if( $ExtensionRegistry === null || $value === 
'composer' ) {
-                               if( $this->detectComposer( $type, $name ) ) {
-                                       $status = 'composer';
-                                       $value = true;
-                               } elseif( $value === 'composer' ) {
-                                       $value = false;
-                                       unset( 
$this->configuration['extensions'][$key] );
-                               }
-                       } elseif( $value === 'require_once' || $value === 
'wfLoad' . ucfirst( $type ) ) {
-                               $status = $value;
-                               $value = true;
-                       // @codingStandardsIgnoreLine
-                       } elseif( $value !== false && ( $status = 
$this->detectLoadingMechanism( $type, $name ) ) ) {
-                               $value = true;
-                       } elseif( $key != 'ExtensionMediaWikiFarm' ) {
-                               if( $value ) {
-                                       $this->log[] = "Requested but missing 
$type $name for wiki {$this->variables['$WIKIID']} in version 
{$this->variables['$VERSION']}";
-                               }
-                               $value = false;
-                               unset( $this->configuration['extensions'][$key] 
);
-                       } else {
-                               $status = $ExtensionRegistry ? 
'wfLoadExtension' : 'require_once';
-                       }
-
-                       if( $status == 'composer' ) {
-                               if( in_array( $key, $composerLoaded ) ) {
-                                       continue;
-                               }
-                               $this->configuration['composer'][] = $key;
-                               if( array_key_exists( $key, $dependencies ) ) {
-                                       $composerLoaded = array_merge( 
$composerLoaded, $dependencies[$key] );
-                                       foreach( $dependencies[$key] as $dep ) {
-                                               if( !array_key_exists( $dep, 
$this->configuration['extensions'] ) ) {
-                                                       
$this->configuration['settings']['wgUse' . preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $dep )] = true;
-                                                       preg_match( 
'/^(Extension|Skin)(.+)$/', $dep, $matches );
-                                                       
$this->configuration['extensions'][$dep] = array( $matches[2], strtolower( 
$matches[1] ), 'composer', - count( $this->configuration['extensions'] ) );
-                                               } else {
-                                                       
$this->configuration['extensions'][$dep][2] = 'composer';
-                                                       
$this->configuration['extensions'][$dep][3] = - abs( 
$this->configuration['extensions'][$dep][3] );
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               # Sort extensions
-               uasort( $this->configuration['extensions'], array( 
'MediaWikiFarm', 'sortExtensions' ) );
-               $i = 0;
-               foreach( $this->configuration['extensions'] as $key => 
&$extension ) {
-                       $extension[3] = $i++;
-               }
-       }
-
-       /**
-        * Detect if the extension can be loaded by Composer.
-        *
-        * This use the backend-generated key; without it, no extension can be 
loaded with Composer in MediaWikiFarm.
-        *
-        * @internal
-        * @mediawikifarm-const
-        *
-        * @param string $type Type, in ['extension', 'skin'].
-        * @param string $name Name of the extension/skin.
-        * @return boolean The extension/skin is Composer-managed (at least for 
its installation).
-        */
-       function detectComposer( $type, $name ) {
-
-               if( is_file( $this->variables['$CODE'] . '/' . $type . 's/' . 
$name . '/composer.json' ) &&
-                   is_dir( $this->variables['$CODE'] . '/vendor/composer' . 
self::composerKey( ucfirst( $type ) . $name ) ) ) {
-
-                       return true;
-               }
-               return false;
-       }
-
-       /**
-        * Detection of the loading mechanism of extensions and skins.
-        *
-        * @internal
-        * @mediawikifarm-const
-        *
-        * @param string $type Type, in ['extension', 'skin'].
-        * @param string $name Name of the extension/skin.
-        * @return string|null Loading mechnism in ['wfLoadExtension', 
'wfLoadSkin', 'require_once', 'composer'] or null if all mechanisms failed.
-        */
-       function detectLoadingMechanism( $type, $name ) {
-
-               if( !is_dir( $this->variables['$CODE'].'/'.$type.'s/'.$name ) ) 
{
-                       return null;
-               }
-
-               # An extension.json/skin.json file is in the directory -> 
assume it is the loading mechanism
-               if( $this->environment['ExtensionRegistry'] && is_file( 
$this->variables['$CODE'].'/'.$type.'s/'.$name.'/'.$type.'.json' ) ) {
-                       return 'wfLoad' . ucfirst( $type );
-               }
-
-               # A composer.json file is in the directory and the extension is 
properly autoloaded by Composer
-               elseif( $this->detectComposer( $type, $name ) ) {
-                       return 'composer';
-               }
-
-               # A MyExtension.php file is in the directory -> assume it is 
the loading mechanism
-               elseif( is_file( 
$this->variables['$CODE'].'/'.$type.'s/'.$name.'/'.$name.'.php' ) ) {
-                       return 'require_once';
-               }
-
-               return null;
-       }
-
-       /**
-        * Sort extensions.
-        *
-        * The extensions are sorted first by loading mechanism, then, for 
Composer-managed
-        * extensions, according to their dependency order.
-        *
-        * @internal
-        *
-        * @param array $a First element.
-        * @param array $b Second element.
-        * @return int Relative order of the two elements.
-        */
-       function sortExtensions( $a, $b ) {
-
-               static $loading = array(
-                       '' => 0,
-                       'composer' => 10,
-                       'require_once' => 20,
-                       'wfLoadSkin' => 30,
-                       'wfLoadExtension' => 30,
-               );
-               static $type = array(
-                       'skin' => 1,
-                       'extension' => 2,
-               );
-
-               $loadA = $a[2] === null ? '' : $a[2];
-               $loadB = $b[2] === null ? '' : $b[2];
-               $weight = $loading[$loadA] + $type[$a[1]] - $loading[$loadB] - 
$type[$b[1]];
-               $stability = $a[3] - $b[3];
-
-               if( $a[2] == 'composer' && $b[2] == 'composer' ) {
-                       # Read the two composer.json, if one is in the require 
section, it must be before
-                       $nameA = ucfirst( $a[1] ) . $a[0];
-                       $nameB = ucfirst( $b[1] ) . $b[0];
-                       $dependencies = $this->readFile( 
'MediaWikiExtensions.php', $this->variables['$CODE'] . '/vendor', false );
-                       if( !$dependencies || !array_key_exists( $nameA, 
$dependencies ) || !array_key_exists( $nameB, $dependencies ) ) {
-                               return $weight ? $weight : $stability;
-                       }
-                       $ArequiresB = in_array( $nameB, $dependencies[$nameA] );
-                       $BrequiresA = in_array( $nameA, $dependencies[$nameB] );
-                       if( $ArequiresB && $BrequiresA ) {
-                               return $stability;
-                       } elseif( $BrequiresA ) {
-                               return -1;
-                       } elseif( $ArequiresB ) {
-                               return 1;
-                       }
-               }
-
-               return $weight ? $weight : $stability;
-       }
-
-       /**
-        * Create a LocalSettings.php.
-        *
-        * A previous mechanism tested in this extension was to load each 
category of
-        * parameters separately (general settings, arrays, skins, extensions) 
given the
-        * cached file [cache]/[farm]/config-VERSION-SUFFIX-WIKIID.php, but 
comparison with
-        * a classical LocalSettings.php was proven to be quicker. Additionally 
debug will
-        * be easier since a LocalSettings.php is easier to read than a 2D 
array.
-        *
-        * @internal
-        *
-        * @param array $configuration Array with the schema defined for 
$this->configuration.
-        * @param string $preconfig PHP code to be added at the top of the file.
-        * @param string $postconfig PHP code to be added at the end of the 
file.
-        * @return string Content of the file LocalSettings.php.
-        */
-       function createLocalSettings( $configuration, $preconfig = '', 
$postconfig = '' ) {
-
-               $localSettings = "<?php\n";
-
-               if( $preconfig ) {
-                       $localSettings .= "\n" . $preconfig;
-               }
-
-               # Sort extensions and skins by loading mechanism
-               $extensions = array(
-                       'extension' => array(
-                               'require_once' => '',
-                               'wfLoadExtension' => '',
-                       ),
-                       'skin' => array(
-                               'require_once' => '',
-                               'wfLoadSkin' => '',
-                       ),
-               );
-               foreach( $configuration['extensions'] as $key => $extension ) {
-                       if( $extension[2] == 'require_once' && ( $key != 
'ExtensionMediaWikiFarm' || !$this->codeDir ) ) {
-                               $extensions[$extension[1]]['require_once'] .= 
"require_once \"\$IP/{$extension[1]}s/{$extension[0]}/{$extension[0]}.php\";\n";
-                       } elseif( $key == 'ExtensionMediaWikiFarm' && 
$extension[2] == 'wfLoadExtension' && $this->codeDir ) {
-                               $extensions['extension']['wfLoadExtension'] .= 
"wfLoadExtension( 'MediaWikiFarm', " . var_export( $this->farmDir . 
'/extension.json', true ) . " );\n";
-                       } elseif( $extension[2] == 'wfLoad' . ucfirst( 
$extension[1] ) ) {
-                               $extensions[$extension[1]]['wfLoad' . ucfirst( 
$extension[1] )] .= 'wfLoad' . ucfirst( $extension[1] ) . '( ' . var_export( 
$extension[0], true ) . " );\n";
-                       }
-               }
-
-               # Skins loaded with require_once
-               if( $extensions['skin']['require_once'] ) {
-                       $localSettings .= "\n# Skins loaded with 
require_once\n";
-                       $localSettings .= $extensions['skin']['require_once'];
-               }
-
-               # Extensions loaded with require_once
-               if( $extensions['extension']['require_once'] ) {
-                       $localSettings .= "\n# Extensions loaded with 
require_once\n";
-                       $localSettings .= 
$extensions['extension']['require_once'];
-               }
-
-               # General settings
-               $localSettings .= "\n# General settings\n";
-               foreach( $configuration['settings'] as $setting => $value ) {
-                       $localSettings .= "\$$setting = " . var_export( $value, 
true ) . ";\n";
-               }
-
-               # Array settings
-               $localSettings .= "\n# Array settings\n";
-               foreach( $configuration['arrays'] as $setting => $value ) {
-                       $localSettings .= "if( !array_key_exists( '$setting', 
\$GLOBALS ) ) {\n\t\$GLOBALS['$setting'] = array();\n}\n";
-               }
-               foreach( $configuration['arrays'] as $setting => $value ) {
-                       $localSettings .= self::writeArrayAssignment( $value, 
"\$$setting" );
-               }
-
-               # Skins loaded with wfLoadSkin
-               if( $extensions['skin']['wfLoadSkin'] ) {
-                       $localSettings .= "\n# Skins\n";
-                       $localSettings .= $extensions['skin']['wfLoadSkin'];
-               }
-
-               # Extensions loaded with wfLoadExtension
-               if( $extensions['extension']['wfLoadExtension'] ) {
-                       $localSettings .= "\n# Extensions\n";
-                       $localSettings .= 
$extensions['extension']['wfLoadExtension'];
-               }
-
-               # Included files
-               $localSettings .= "\n# Included files\n";
-               foreach( $configuration['execFiles'] as $execFile ) {
-                       $localSettings .= "include '$execFile';\n";
-               }
-
-               if( $postconfig ) {
-                       $localSettings .= "\n" . $postconfig;
-               }
-
-               return $localSettings;
-       }
-
-       /**
         * Set a wiki property and replace placeholders (property name version).
         *
         * @internal
@@ -1970,61 +1423,5 @@
                }
 
                return $out;
-       }
-
-       /**
-        * Write an 'array diff' (when only a subarray is modified) in plain 
PHP.
-        *
-        * Note that, given PHP lists and dictionaries use the same syntax, 
this function
-        * try to recognise a list when the array diff has exactly the keys 0, 
1, 2, 3,…
-        * but there could be false positives.
-        *
-        * @api
-        * @mediawikifarm-const
-        * @mediawikifarm-idempotent
-        * @SuppressWarning(PHPMD.StaticAccess)
-        *
-        * @param array $array The 'array diff' (part of an array to be 
modified).
-        * @param string $prefix The beginning of the plain PHP, should be 
something like '$myArray'.
-        * @return string The plain PHP for this array assignment.
-        */
-       static function writeArrayAssignment( $array, $prefix ) {
-
-               $result = '';
-               $isList = ( count( array_diff( array_keys( $array ), range( 0, 
count( $array ) ) ) ) == 0 );
-               foreach( $array as $key => $value ) {
-                       $newkey = '[' . var_export( $key, true ) . ']';
-                       if( $isList ) {
-                               $result .= $prefix . '[] = ' . var_export( 
$value, true ) . ";\n";
-                       } elseif( is_array( $value ) ) {
-                               $result .= self::writeArrayAssignment( $value, 
$prefix . $newkey );
-                       } else {
-                               $result .= $prefix . $newkey . ' = ' . 
var_export( $value, true ) . ";\n";
-                       }
-               }
-
-               return $result;
-       }
-
-       /**
-        * Composer key depending on the activated extensions and skins.
-        *
-        * Extension names should follow the form 
'ExtensionMyWonderfulExtension';
-        * Skin names should follow the form 'SkinMyWonderfulSkin'.
-        *
-        * @api
-        * @mediawikifarm-const
-        * @mediawikifarm-idempotent
-        *
-        * @param string $name Name of extension or skin.
-        * @return string Composer key.
-        */
-       static function composerKey( $name ) {
-
-               if( $name == '' ) {
-                       return '';
-               }
-
-               return substr( md5( $name ), 0, 8 );
        }
 }
diff --git a/src/MediaWikiFarmComposerScript.php 
b/src/MediaWikiFarmComposerScript.php
index ea755b4..2779811 100644
--- a/src/MediaWikiFarmComposerScript.php
+++ b/src/MediaWikiFarmComposerScript.php
@@ -184,13 +184,13 @@
 
                        $thisInstallation = $baseComposerJson;
                        $thisInstallation['require'][$composerName] = 
$installable[$composerName];
-                       $thisInstallation['config']['autoloader-suffix'] = 
MediaWikiFarm::composerKey( $name );
+                       $thisInstallation['config']['autoloader-suffix'] = 
MediaWikiFarmConfiguration::composerKey( $name );
 
                        if( !$quiet ) {
                                // @codeCoverageIgnoreStart
                                echo $icounter . '. Composer set for ';
                                echo lcfirst( preg_replace( 
'/^(Extension|Skin)/', '$1 ', $extensions[$composerName] ) ) . ' (';
-                               echo MediaWikiFarm::composerKey( $name ) . 
"):\n";
+                               echo MediaWikiFarmConfiguration::composerKey( 
$name ) . "):\n";
                                // @codeCoverageIgnoreEnd
                        }
 
@@ -206,7 +206,7 @@
                                // @codeCoverageIgnoreEnd
                        }
 
-                       self::copyr( 'vendor/composer', 
'vendor-composer/composer' . MediaWikiFarm::composerKey( $name ),
+                       self::copyr( 'vendor/composer', 
'vendor-composer/composer' . MediaWikiFarmConfiguration::composerKey( $name ),
                                     true, array(), array( '/autoload_.*\.php', 
'/ClassLoader\.php', '/installed\.json' )
                        );
                        $icounter++;
diff --git a/src/MediaWikiFarmConfiguration.php 
b/src/MediaWikiFarmConfiguration.php
new file mode 100644
index 0000000..3f2d901
--- /dev/null
+++ b/src/MediaWikiFarmConfiguration.php
@@ -0,0 +1,745 @@
+<?php
+/**
+ * Class MediaWikiFarmConfiguration.
+ *
+ * @package MediaWikiFarm
+ * @author Sébastien Beyou ~ Seb35 <[email protected]>
+ * @license GPL-3.0+ GNU General Public License v3.0 ou version ultérieure
+ * @license AGPL-3.0+ GNU Affero General Public License v3.0 ou version 
ultérieure
+ */
+
+
+/**
+ * Class dedicated to configuration compilation.
+ */
+class MediaWikiFarmConfiguration {
+
+       /*
+        * Properties
+        * ---------- */
+
+       /** @var MediaWikiFarm|null Main object. */
+       protected $farm = null;
+
+       /** @var array Environment. */
+       protected $environment = array(
+               'ExtensionRegistry' => null,
+       );
+
+       /** @var array Configuration parameters for this wiki. */
+       protected $configuration = array(
+               'settings' => array(),
+               'arrays' => array(),
+               'extensions' => array(),
+               'execFiles' => array(),
+               'composer' => array(),
+       );
+
+
+
+       /*
+        * Functions of interest in normal operations
+        * ------------------------------------------ */
+
+       /**
+        * Construction.
+        *
+        * @param MediaWikiFarm $farm Main object.
+        * @return MediaWikiFarmConfiguration
+        */
+       function __construct( &$farm ) {
+
+               $this->farm = $farm;
+       }
+
+       /**
+        * Get MediaWiki configuration.
+        *
+        * This associative array contains four sections:
+        *   - 'settings': associative array of MediaWiki configuration (e.g. 
'wgServer' => '//example.org');
+        *   - 'arrays': associative array of MediaWiki configuration of type 
array (e.g. 'wgGroupPermissions' => array( 'edit' => false ));
+        *   - 'extensions': list of extensions and skins (e.g. 0 => array( 
'ParserFunctions', 'extension', 'wfLoadExtension' ));
+        *   - 'composer': list of Composer-installed extensions and skins 
(e.g. 0 => 'ExtensionSemanticMediaWiki');
+        *   - 'execFiles': list of PHP files to execute at the end.
+        *
+        * @api
+        * @mediawikifarm-const
+        *
+        * @param string|false $key Key of the wanted section or false for the 
whole array.
+        * @param string|false $key2 Subkey (specific to each entry) or false 
for the whole entry.
+        * @return array MediaWiki configuration, either entire, either a part 
depending on the parameter.
+        */
+       function getConfiguration( $key = false, $key2 = false ) {
+               if( $key !== false ) {
+                       if( array_key_exists( $key, $this->configuration ) ) {
+                               if( $key2 !== false && array_key_exists( $key2, 
$this->configuration[$key] ) ) {
+                                       return 
$this->configuration[$key][$key2];
+                               } elseif( $key2 !== false ) {
+                                       return null;
+                               }
+                               return $this->configuration[$key];
+                       }
+                       return null;
+               }
+               return $this->configuration;
+       }
+
+       /**
+        * Set the 'composer' key in the configuration.
+        *
+        * @param string[] $composer List of Composer-installed extensions.
+        * @return void
+        */
+       function setComposer( $composer ) {
+
+               $this->configuration['composer'] = $composer;
+       }
+
+       /**
+        * Popuplate the settings array directly from config files (without 
wgConf).
+        *
+        * There should be no major differences is results between this 
function and results
+        * of SiteConfiguration::getAll(), but probably some edge cases. At the 
contrary of
+        * Siteconfiguration, this implementation is focused on performance for 
current wiki:
+        * only the parameters for current wikis are issued, contrary to 
wgConf’s strategy
+        * map-all-and-reduce. An additional loop over config files is here; 
wgConf delegates
+        * this externally if wanted.
+        *
+        * The priories used here are implicit in wgConf but exist and behave 
similarly:
+        * 0 = default value from MW; 1 = explicit very default value from a 
specific file;
+        * 2 = standard default value; 3 = value with suffix-priority;
+        * 4 = value with tag-priority; 5 = value with specific-wiki-priority. 
Files are
+        * processed in-order and linearly; for a given setting, only values 
with a greater
+        * or equal priority can override a previous value.
+        *
+        * There are two resulting arrays in the object property array 
'configuration':
+        *   - settings: scalar (or array) values overriding the default MW 
values;
+        *   - arrays: array values merged into the default MW values.
+        * They are processed differently given their different nature, and to 
facilitate
+        * mass-import into global scope (or other configuration object). 
Another minor
+        * reason is: if this processing is done on a MediaWiki installation in 
a version
+        * different from the target version (sort of cross-compilation), the 
compiling
+        * MW is not aware of the default array value of the target MW, so it is
+        * safer to only manipulate the known difference.
+        *
+        * @internal
+        * @SuppressWarnings(PHPMD.ElseExpression)
+        * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+        *
+        * @return bool Success.
+        */
+       function populateSettings() {
+
+               $settings = &$this->configuration['settings'];
+               $priorities = array();
+               $settingsArray = &$this->configuration['arrays'];
+               $prioritiesArray = array();
+
+               $extensions =& $this->configuration['extensions'];
+
+               $settings['wgUseExtensionMediaWikiFarm'] = true;
+               $extensions['ExtensionMediaWikiFarm'] = array( 'MediaWikiFarm', 
'extension', null, 0 );
+
+               $farmConfig = $this->farm->getFarmConfiguration();
+
+               foreach( $farmConfig['config'] as $configFile ) {
+
+                       if( !is_array( $configFile ) ) {
+                               continue;
+                       }
+
+                       # Replace variables
+                       $configFile = $this->farm->replaceVariables( 
$configFile );
+
+                       # Executable config files
+                       if( array_key_exists( 'executable', $configFile ) && 
$configFile['executable'] ) {
+
+                               $this->configuration['execFiles'][] = 
$this->farm->getConfigDir() . '/' . $configFile['file'];
+                               continue;
+                       }
+
+                       $theseSettings = $this->farm->readFile( 
$configFile['file'], $this->farm->getConfigDir() );
+                       if( $theseSettings === false ) {
+                               # If a file is unavailable, skip it
+                               continue;
+                       }
+
+                       # Defined key
+                       if( strpos( $configFile['key'], '*' ) === false ) {
+
+                               $priority = 0;
+                               if( $configFile['key'] == 'default' ) {
+                                       $priority = 1;
+                               } elseif( $configFile['key'] == 
$this->farm->getVariable( '$SUFFIX' ) ) {
+                                       $priority = 3;
+                               } elseif( $configFile['key'] == 
$this->farm->getVariable( '$WIKIID' ) ) {
+                                       $priority = 5;
+                               } else {
+                                       /*foreach( $tags as $tag ) {
+                                               if( $configFile['key'] == $tag 
) {
+                                                       $priority = 4;
+                                                       break;
+                                               }
+                                       }*/
+                                       if( $priority == 0 ) {
+                                               continue;
+                                       }
+                               }
+
+                               foreach( $theseSettings as $rawSetting => 
$value ) {
+
+                                       # Sanitise the setting name
+                                       $setting = preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $rawSetting );
+
+                                       if( substr( $rawSetting, 0, 1 ) == '+' 
) {
+                                               if( !array_key_exists( 
$setting, $prioritiesArray ) || $prioritiesArray[$setting] <= $priority ) {
+                                                       
$settingsArray[$setting] = $value;
+                                                       
$prioritiesArray[$setting] = $priority;
+                                               }
+                                       }
+                                       elseif( !array_key_exists( $setting, 
$priorities ) || $priorities[$setting] <= $priority ) {
+                                               $settings[$setting] = $value;
+                                               $priorities[$setting] = 
$priority;
+                                               if( substr( $setting, 0, 14 ) 
== 'wgUseExtension' ) {
+                                                       $extensions['Extension' 
. substr( $rawSetting, 14 )] = array( substr( $rawSetting, 14 ), 'extension', 
null, count( $extensions ) );
+                                               } elseif( substr( $setting, 0, 
9 ) == 'wgUseSkin' ) {
+                                                       $extensions['Skin' . 
substr( $rawSetting, 9 )] = array( substr( $rawSetting, 9 ), 'skin', null, 
count( $extensions ) );
+                                               }
+                                       }
+                               }
+                       }
+
+                       # Regex key
+                       else {
+
+                               // $tags = array(); # @todo data sources not 
implemented, but code to selection parameters from a tag is below
+
+                               $defaultKey = '';
+                               $classicKey = '';
+                               if( array_key_exists( 'default', $configFile ) 
&& is_string( $configFile['default'] ) ) {
+                                       $defaultKey = 
$this->farm->replaceVariables( $configFile['default'] );
+                               }
+                               if( is_string( $configFile['key'] ) ) {
+                                       $classicKey = 
$this->farm->replaceVariables( $configFile['key'] );
+                               }
+
+                               # These are precomputations of the condition 
`$classicKey == $wikiID` (is current wiki equal to key indicated in config 
file?)
+                               # to avoid recompute it each time in the loop. 
This is a bit more complex to take into account the star: $wikiID is the part
+                               # corresponding to the star from the variable 
$WIKIID if $classicKey can match $WIKIID when remplacing the star by something
+                               # (the star will be the key in the files). This 
reasonning is “inversed” compared to a loop checking each key in the files
+                               # in order to use array_key_exists, assumed to 
be quicker than a direct loop.
+                               $wikiIDKey = (bool) preg_match( 
'/^'.str_replace( '*', '(.+)', $classicKey ).'$/', $this->farm->getVariable( 
'$WIKIID' ), $matches );
+                               $wikiID = $wikiIDKey ? $matches[1] : 
$this->farm->getVariable( '$WIKIID' );
+                               $suffixKey = (bool) preg_match( 
'/^'.str_replace( '*', '(.+)', $classicKey ).'$/', $this->farm->getVariable( 
'$SUFFIX' ), $matches );
+                               $suffix = $suffixKey ? $matches[1] : 
$this->farm->getVariable( '$SUFFIX' );
+                               /*$tagKey = array();
+                               foreach( $tags as $tag ) {
+                                       $tagKey[$tag] = ($classicKey == $tag);
+                               }*/
+                               if( $defaultKey ) {
+                                       $suffixDefaultKey = (bool) preg_match( 
'/^'.str_replace( '*', '(.+)', $defaultKey ).'$/', $this->farm->getVariable( 
'$SUFFIX' ), $matches );
+                                       // $tagDefaultKey = in_array( 
$defaultKey, $tags );
+                               }
+
+                               foreach( $theseSettings as $rawSetting => 
$values ) {
+
+                                       # Sanitise the setting name
+                                       $setting = preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $rawSetting );
+
+                                       # Depending if it is an array diff or 
not, create and initialise the variables
+                                       if( substr( $rawSetting, 0, 1 ) == '+' 
) {
+                                               $settingIsArray = true;
+                                               if( !array_key_exists( 
$setting, $prioritiesArray ) ) {
+                                                       
$settingsArray[$setting] = array();
+                                                       
$prioritiesArray[$setting] = 0;
+                                               }
+                                               $thisSetting =  
&$settingsArray[$setting];
+                                               $thisPriority = 
&$prioritiesArray[$setting];
+                                       } else {
+                                               $settingIsArray = false;
+                                               if( !array_key_exists( 
$setting, $priorities ) ) {
+                                                       $settings[$setting] = 
null;
+                                                       $priorities[$setting] = 
0;
+                                               }
+                                               $thisSetting =  
&$settings[$setting];
+                                               $thisPriority = 
&$priorities[$setting];
+                                               if( substr( $setting, 0, 14 ) 
== 'wgUseExtension' ) {
+                                                       $extensions['Extension' 
. substr( $rawSetting, 14 )] = array( substr( $rawSetting, 14 ), 'extension', 
null, count( $extensions ) );
+                                               } elseif( substr( $setting, 0, 
9 ) == 'wgUseSkin' ) {
+                                                       $extensions['Skin' . 
substr( $rawSetting, 9 )] = array( substr( $rawSetting, 9 ), 'skin', null, 
count( $extensions ) );
+                                               }
+                                       }
+
+                                       # Set value if there is a label 
corresponding to wikiID
+                                       if( $wikiIDKey ) {
+                                               if( array_key_exists( $wikiID, 
$values ) ) {
+                                                       $thisSetting = 
$values[$wikiID];
+                                                       $thisPriority = 5;
+                                                       continue;
+                                               }
+                                               if( array_key_exists( 
'+'.$wikiID, $values ) && is_array( $values['+'.$wikiID] ) ) {
+                                                       $thisSetting = 
MediaWikiFarm::arrayMerge( $thisSetting, $values['+'.$wikiID] );
+                                                       $thisPriority = 3;
+                                               }
+                                       }
+
+                                       # Set value if there are labels 
corresponding to given tags
+                                       /*$setted = false;
+                                       foreach( $tags as $tag ) {
+                                               if( $tagKey[$tag] && 
$thisPriority <= 4 ) {
+                                                       if( array_key_exists( 
$tag, $values ) ) {
+                                                               $thisSetting = 
$value[$tag];
+                                                               $thisPriority = 
4;
+                                                               $setted = true;
+                                                               # NB: for 
strict equivalence with wgConf there should be here a `break`, but by 
consistency
+                                                               # (last value 
kept) and given the case should not appear, there is no.
+                                                       }
+                                                       elseif( 
array_key_exists( '+'.$tag, $values ) && is_array( $values['+'.$tag] ) ) {
+                                                               $thisSetting = 
MediaWikiFarm::arrayMerge( $thisSetting, $values['+'.$tag] );
+                                                               $thisPriority = 
3;
+                                                       }
+                                               }
+                                       }
+                                       if( $setted ) {
+                                               continue;
+                                       }*/
+
+                                       # Set value if there is a label 
corresponding to suffix
+                                       if( $suffixKey && $thisPriority <= 3 ) {
+                                               if( array_key_exists( $suffix, 
$values ) ) {
+                                                       $thisSetting = 
$values[$suffix];
+                                                       $thisPriority = 3;
+                                                       continue;
+                                               }
+                                               if( array_key_exists( 
'+'.$suffix, $values ) && is_array( $values['+'.$suffix] ) ) {
+                                                       $thisSetting = 
MediaWikiFarm::arrayMerge( $thisSetting, $values['+'.$suffix] );
+                                                       $thisPriority = 3;
+                                               }
+                                       }
+
+                                       # Default value
+                                       if( $thisPriority <= 2 && 
array_key_exists( 'default', $values ) ) {
+                                               $thisSetting = 
$values['default'];
+                                               $thisPriority = 2;
+                                               if( $defaultKey ) {
+                                                       if( $suffixDefaultKey ) 
{
+                                                               $thisPriority = 
3;
+                                                       /*} elseif( 
$tagDefaultKey ) {
+                                                               $thisPriority = 
4;*/
+                                                       }
+                                               }
+                                               continue;
+                                       }
+
+                                       # Nothing was selected, clean up
+                                       if( $thisPriority == 0 ) {
+                                               if( $settingIsArray ) {
+                                                       unset( 
$settingsArray[$setting] );
+                                                       unset( 
$prioritiesArray[$setting] );
+                                               } else {
+                                                       unset( 
$settings[$setting] );
+                                                       unset( 
$priorities[$setting] );
+                                                       if( substr( $setting, 
0, 14 ) == 'wgUseExtension' ) {
+                                                               unset( 
$extensions['Extension' . substr( $rawSetting, 14 )] );
+                                                       } elseif( substr( 
$setting, 0, 9 ) == 'wgUseSkin' ) {
+                                                               unset( 
$extensions['Skin' . substr( $rawSetting, 9 )] );
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * Set environment, i.e. every 'environment variables' which lead to a 
known configuration.
+        *
+        * For now, the only environment variable is ExtensionRegistry (is the 
MediaWiki version
+        * capable of loading extensions/skins with 
wfLoadExtension/wfLoadSkin?).
+        *
+        * @internal
+        *
+        * @param string|null $key Set the keyed environment variable or all 
environment variables.
+        * @param mixed|null $value Value of the keyed environment variable.
+        * @return void
+        */
+       function setEnvironment( $key = null, $value = null ) {
+
+               if( $key === null ) {
+                       $key = 'ExtensionRegistry';
+               }
+
+               # Set environment
+               if( $key == 'ExtensionRegistry' ) {
+                       if( $value === null ) {
+                               $value = class_exists( 'ExtensionRegistry' );
+                       }
+                       $this->environment['ExtensionRegistry'] = $value;
+               }
+       }
+
+       /**
+        * Activate extensions and skins depending on their autoloading and 
activation mechanisms.
+        *
+        * When the environment parameter ExtensionRegistry is not set (null), 
only Composer-enabled
+        * extensions and skins are Composer-autoloaded; and if 
ExtensionRegistry is set to true or
+        * false, extensions and skins are activated through 
wfLoadExtension/wfLoadSkin or require_once.
+        *
+        * The part related to Composer is a bit complicated (partly since 
optimised): when an extension
+        * is Composer-managed, it is checked if it was already loaded by 
another extension (in which
+        * case Composer has autoloaded its code), then it is registered as 
Composer-managed, then its
+        * required extensions are registered. This last part is important, 
else Composer would have
+        * silently autoloaded the required extensions, but these would not be 
known by MediaWikiFarm
+        * and, more importantly, an eventual wfLoadExtension would not be 
triggered (e.g. PageForms 4.0+
+        * is a Composer dependency of the Composer-installed 
SemanticFormsSelect; if you activate SFS
+        * but not PF, PF would not be wfLoadExtension’ed – since unknown from 
MediaWikiFarm – and the
+        * wfLoadExtension’s SFS issues a fatal error since PF is not 
wfLoadExtension’ed, even if it is
+        * Composer-installed).
+        *
+        * @internal
+        *
+        * @return void
+        */
+       function activateExtensions() {
+
+               # Autodetect if ExtensionRegistry is here
+               $ExtensionRegistry = $this->environment['ExtensionRegistry'];
+
+               # Load Composer dependencies if available
+               $composerLoaded = array();
+               $dependencies = $this->farm->readFile( 
'MediaWikiExtensions.php', $this->farm->getVariable( '$CODE' ) . '/vendor', 
false );
+               if( !$dependencies ) {
+                       $dependencies = array();
+               }
+
+               # Search for skin and extension activation
+               foreach( $this->configuration['extensions'] as $key => 
&$extension ) {
+
+                       $type = $extension[1];
+                       $name = $extension[0];
+                       $status =& $extension[2];
+
+                       $setting = 'wgUse' . preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $key );
+                       $value =& $this->configuration['settings'][$setting];
+
+                       if( $ExtensionRegistry === null || $value === 
'composer' ) {
+                               if( $this->detectComposer( $type, $name ) ) {
+                                       $status = 'composer';
+                                       $value = true;
+                               } elseif( $value === 'composer' ) {
+                                       $value = false;
+                                       unset( 
$this->configuration['extensions'][$key] );
+                               }
+                       } elseif( $value === 'require_once' || $value === 
'wfLoad' . ucfirst( $type ) ) {
+                               $status = $value;
+                               $value = true;
+                       // @codingStandardsIgnoreLine
+                       } elseif( $value !== false && ( $status = 
$this->detectLoadingMechanism( $type, $name ) ) ) {
+                               $value = true;
+                       } elseif( $key != 'ExtensionMediaWikiFarm' ) {
+                               if( $value ) {
+                                       $this->farm->log[] = "Requested but 
missing $type $name for wiki " .
+                                               $this->farm->getVariable( 
'$WIKIID' ) . ' in version ' .
+                                               $this->farm->getVariable( 
'$VERSION' );
+                               }
+                               $value = false;
+                               unset( $this->configuration['extensions'][$key] 
);
+                       } else {
+                               $status = $ExtensionRegistry ? 
'wfLoadExtension' : 'require_once';
+                       }
+
+                       if( $status == 'composer' ) {
+                               if( in_array( $key, $composerLoaded ) ) {
+                                       continue;
+                               }
+                               $this->configuration['composer'][] = $key;
+                               if( array_key_exists( $key, $dependencies ) ) {
+                                       $composerLoaded = array_merge( 
$composerLoaded, $dependencies[$key] );
+                                       foreach( $dependencies[$key] as $dep ) {
+                                               if( !array_key_exists( $dep, 
$this->configuration['extensions'] ) ) {
+                                                       
$this->configuration['settings']['wgUse' . preg_replace( 
'/[^a-zA-Z0-9_\x7f\xff]/', '', $dep )] = true;
+                                                       preg_match( 
'/^(Extension|Skin)(.+)$/', $dep, $matches );
+                                                       
$this->configuration['extensions'][$dep] = array( $matches[2], strtolower( 
$matches[1] ), 'composer', - count( $this->configuration['extensions'] ) );
+                                               } else {
+                                                       
$this->configuration['extensions'][$dep][2] = 'composer';
+                                                       
$this->configuration['extensions'][$dep][3] = - abs( 
$this->configuration['extensions'][$dep][3] );
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               # Sort extensions
+               uasort( $this->configuration['extensions'], array( 
'MediaWikiFarmConfiguration', 'sortExtensions' ) );
+               $i = 0;
+               foreach( $this->configuration['extensions'] as $key => 
&$extension ) {
+                       $extension[3] = $i++;
+               }
+       }
+
+       /**
+        * Detect if the extension can be loaded by Composer.
+        *
+        * This use the backend-generated key; without it, no extension can be 
loaded with Composer in MediaWikiFarm.
+        *
+        * @internal
+        * @mediawikifarm-const
+        *
+        * @param string $type Type, in ['extension', 'skin'].
+        * @param string $name Name of the extension/skin.
+        * @return boolean The extension/skin is Composer-managed (at least for 
its installation).
+        */
+       function detectComposer( $type, $name ) {
+
+               if( is_file( $this->farm->getVariable( '$CODE' ) . '/' . $type 
. 's/' . $name . '/composer.json' ) &&
+                   is_dir( $this->farm->getVariable( '$CODE' ) . 
'/vendor/composer' . self::composerKey( ucfirst( $type ) . $name ) ) ) {
+
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * Detection of the loading mechanism of extensions and skins.
+        *
+        * @internal
+        * @mediawikifarm-const
+        *
+        * @param string $type Type, in ['extension', 'skin'].
+        * @param string $name Name of the extension/skin.
+        * @return string|null Loading mechnism in ['wfLoadExtension', 
'wfLoadSkin', 'require_once', 'composer'] or null if all mechanisms failed.
+        */
+       function detectLoadingMechanism( $type, $name ) {
+
+               if( !is_dir( $this->farm->getVariable( '$CODE' 
).'/'.$type.'s/'.$name ) ) {
+                       return null;
+               }
+
+               # An extension.json/skin.json file is in the directory -> 
assume it is the loading mechanism
+               if( $this->environment['ExtensionRegistry'] && is_file( 
$this->farm->getVariable( '$CODE' ).'/'.$type.'s/'.$name.'/'.$type.'.json' ) ) {
+                       return 'wfLoad' . ucfirst( $type );
+               }
+
+               # A composer.json file is in the directory and the extension is 
properly autoloaded by Composer
+               elseif( $this->detectComposer( $type, $name ) ) {
+                       return 'composer';
+               }
+
+               # A MyExtension.php file is in the directory -> assume it is 
the loading mechanism
+               elseif( is_file( $this->farm->getVariable( '$CODE' 
).'/'.$type.'s/'.$name.'/'.$name.'.php' ) ) {
+                       return 'require_once';
+               }
+
+               return null;
+       }
+
+       /**
+        * Sort extensions.
+        *
+        * The extensions are sorted first by loading mechanism, then, for 
Composer-managed
+        * extensions, according to their dependency order.
+        *
+        * @internal
+        *
+        * @param array $a First element.
+        * @param array $b Second element.
+        * @return int Relative order of the two elements.
+        */
+       function sortExtensions( $a, $b ) {
+
+               static $loading = array(
+                       '' => 0,
+                       'composer' => 10,
+                       'require_once' => 20,
+                       'wfLoadSkin' => 30,
+                       'wfLoadExtension' => 30,
+               );
+               static $type = array(
+                       'skin' => 1,
+                       'extension' => 2,
+               );
+
+               $loadA = $a[2] === null ? '' : $a[2];
+               $loadB = $b[2] === null ? '' : $b[2];
+               $weight = $loading[$loadA] + $type[$a[1]] - $loading[$loadB] - 
$type[$b[1]];
+               $stability = $a[3] - $b[3];
+
+               if( $a[2] == 'composer' && $b[2] == 'composer' ) {
+                       # Read the two composer.json, if one is in the require 
section, it must be before
+                       $nameA = ucfirst( $a[1] ) . $a[0];
+                       $nameB = ucfirst( $b[1] ) . $b[0];
+                       $dependencies = $this->farm->readFile( 
'MediaWikiExtensions.php', $this->farm->getVariable( '$CODE' ) . '/vendor', 
false );
+                       if( !$dependencies || !array_key_exists( $nameA, 
$dependencies ) || !array_key_exists( $nameB, $dependencies ) ) {
+                               return $weight ? $weight : $stability;
+                       }
+                       $ArequiresB = in_array( $nameB, $dependencies[$nameA] );
+                       $BrequiresA = in_array( $nameA, $dependencies[$nameB] );
+                       if( $ArequiresB && $BrequiresA ) {
+                               return $stability;
+                       } elseif( $BrequiresA ) {
+                               return -1;
+                       } elseif( $ArequiresB ) {
+                               return 1;
+                       }
+               }
+
+               return $weight ? $weight : $stability;
+       }
+
+       /**
+        * Create a LocalSettings.php.
+        *
+        * A previous mechanism tested in this extension was to load each 
category of
+        * parameters separately (general settings, arrays, skins, extensions) 
given the
+        * cached file [cache]/[farm]/config-VERSION-SUFFIX-WIKIID.php, but 
comparison with
+        * a classical LocalSettings.php was proven to be quicker. Additionally 
debug will
+        * be easier since a LocalSettings.php is easier to read than a 2D 
array.
+        *
+        * @internal
+        *
+        * @param array $configuration Array with the schema defined for 
$this->configuration.
+        * @param boolean $isMonoversion Is MediaWikiFarm configured for 
monoversion?
+        * @param string $preconfig PHP code to be added at the top of the file.
+        * @param string $postconfig PHP code to be added at the end of the 
file.
+        * @return string Content of the file LocalSettings.php.
+        */
+       static function createLocalSettings( $configuration, $isMonoversion, 
$preconfig = '', $postconfig = '' ) {
+
+               $localSettings = "<?php\n";
+
+               if( $preconfig ) {
+                       $localSettings .= "\n" . $preconfig;
+               }
+
+               # Sort extensions and skins by loading mechanism
+               $extensions = array(
+                       'extension' => array(
+                               'require_once' => '',
+                               'wfLoadExtension' => '',
+                       ),
+                       'skin' => array(
+                               'require_once' => '',
+                               'wfLoadSkin' => '',
+                       ),
+               );
+               foreach( $configuration['extensions'] as $key => $extension ) {
+                       if( $extension[2] == 'require_once' && ( $key != 
'ExtensionMediaWikiFarm' || !$isMonoversion ) ) {
+                               $extensions[$extension[1]]['require_once'] .= 
"require_once \"\$IP/{$extension[1]}s/{$extension[0]}/{$extension[0]}.php\";\n";
+                       } elseif( $key == 'ExtensionMediaWikiFarm' && 
$extension[2] == 'wfLoadExtension' && $isMonoversion ) {
+                               $extensions['extension']['wfLoadExtension'] .= 
"wfLoadExtension( 'MediaWikiFarm', " .
+                                       var_export( dirname( dirname( __FILE__ 
) ) . '/extension.json', true ) . " );\n";
+                       } elseif( $extension[2] == 'wfLoad' . ucfirst( 
$extension[1] ) ) {
+                               $extensions[$extension[1]]['wfLoad' . ucfirst( 
$extension[1] )] .= 'wfLoad' . ucfirst( $extension[1] ) . '( ' . var_export( 
$extension[0], true ) . " );\n";
+                       }
+               }
+
+               # Skins loaded with require_once
+               if( $extensions['skin']['require_once'] ) {
+                       $localSettings .= "\n# Skins loaded with 
require_once\n";
+                       $localSettings .= $extensions['skin']['require_once'];
+               }
+
+               # Extensions loaded with require_once
+               if( $extensions['extension']['require_once'] ) {
+                       $localSettings .= "\n# Extensions loaded with 
require_once\n";
+                       $localSettings .= 
$extensions['extension']['require_once'];
+               }
+
+               # General settings
+               $localSettings .= "\n# General settings\n";
+               foreach( $configuration['settings'] as $setting => $value ) {
+                       $localSettings .= "\$$setting = " . var_export( $value, 
true ) . ";\n";
+               }
+
+               # Array settings
+               $localSettings .= "\n# Array settings\n";
+               foreach( $configuration['arrays'] as $setting => $value ) {
+                       $localSettings .= "if( !array_key_exists( '$setting', 
\$GLOBALS ) ) {\n\t\$GLOBALS['$setting'] = array();\n}\n";
+               }
+               foreach( $configuration['arrays'] as $setting => $value ) {
+                       $localSettings .= self::writeArrayAssignment( $value, 
"\$$setting" );
+               }
+
+               # Skins loaded with wfLoadSkin
+               if( $extensions['skin']['wfLoadSkin'] ) {
+                       $localSettings .= "\n# Skins\n";
+                       $localSettings .= $extensions['skin']['wfLoadSkin'];
+               }
+
+               # Extensions loaded with wfLoadExtension
+               if( $extensions['extension']['wfLoadExtension'] ) {
+                       $localSettings .= "\n# Extensions\n";
+                       $localSettings .= 
$extensions['extension']['wfLoadExtension'];
+               }
+
+               # Included files
+               $localSettings .= "\n# Included files\n";
+               foreach( $configuration['execFiles'] as $execFile ) {
+                       $localSettings .= "include '$execFile';\n";
+               }
+
+               if( $postconfig ) {
+                       $localSettings .= "\n" . $postconfig;
+               }
+
+               return $localSettings;
+       }
+
+       /**
+        * Write an 'array diff' (when only a subarray is modified) in plain 
PHP.
+        *
+        * Note that, given PHP lists and dictionaries use the same syntax, 
this function
+        * try to recognise a list when the array diff has exactly the keys 0, 
1, 2, 3,…
+        * but there could be false positives.
+        *
+        * @api
+        * @mediawikifarm-const
+        * @mediawikifarm-idempotent
+        * @SuppressWarning(PHPMD.StaticAccess)
+        *
+        * @param array $array The 'array diff' (part of an array to be 
modified).
+        * @param string $prefix The beginning of the plain PHP, should be 
something like '$myArray'.
+        * @return string The plain PHP for this array assignment.
+        */
+       static function writeArrayAssignment( $array, $prefix ) {
+
+               $result = '';
+               $isList = ( count( array_diff( array_keys( $array ), range( 0, 
count( $array ) ) ) ) == 0 );
+               foreach( $array as $key => $value ) {
+                       $newkey = '[' . var_export( $key, true ) . ']';
+                       if( $isList ) {
+                               $result .= $prefix . '[] = ' . var_export( 
$value, true ) . ";\n";
+                       } elseif( is_array( $value ) ) {
+                               $result .= self::writeArrayAssignment( $value, 
$prefix . $newkey );
+                       } else {
+                               $result .= $prefix . $newkey . ' = ' . 
var_export( $value, true ) . ";\n";
+                       }
+               }
+
+               return $result;
+       }
+
+       /**
+        * Composer key depending on the activated extensions and skins.
+        *
+        * Extension names should follow the form 
'ExtensionMyWonderfulExtension';
+        * Skin names should follow the form 'SkinMyWonderfulSkin'.
+        *
+        * @api
+        * @mediawikifarm-const
+        * @mediawikifarm-idempotent
+        *
+        * @param string $name Name of extension or skin.
+        * @return string Composer key.
+        */
+       static function composerKey( $name ) {
+
+               if( $name == '' ) {
+                       return '';
+               }
+
+               return substr( md5( $name ), 0, 8 );
+       }
+}
diff --git a/tests/perfs/MediaWikiFarmTestPerfs.php 
b/tests/perfs/MediaWikiFarmTestPerfs.php
index 37e87b9..7bf4e4c 100644
--- a/tests/perfs/MediaWikiFarmTestPerfs.php
+++ b/tests/perfs/MediaWikiFarmTestPerfs.php
@@ -155,13 +155,14 @@
         * This function is very similar to its parent but adds counters in the 
file.
         *
         * @param array $configuration Array with the schema defined for 
$this->configuration.
+        * @param boolean $isMonoversion Is MediaWikiFarm configured for 
monoversion?
         * @param string $preconfig PHP code to be added at the top of the file.
         * @param string $postconfig PHP code to be added at the end of the 
file.
         * @return string Content of the file LocalSettings.php.
         */
-       function createLocalSettings( $configuration, $preconfig = '', 
$postconfig = '' ) {
+       static function createLocalSettings( $configuration, $isMonoversion, 
$preconfig = '', $postconfig = '' ) {
 
-               return parent::createLocalSettings( $configuration,
+               return parent::createLocalSettings( $configuration, 
$isMonoversion,
                        "# Start counter\nif( class_exists( 
'MediaWikiFarmTestPerfs' ) ) {\n\tMediaWikiFarmTestPerfs::startCounter( 
'config' );\n}\n",
                        "# Stop counter\nif( class_exists( 
'MediaWikiFarmTestPerfs' ) ) {\n\tMediaWikiFarmTestPerfs::stopCounter( 'config' 
);" .
                                
"\n\tMediaWikiFarmTestPerfs::writeResults();\n}\n"
diff --git a/tests/phpunit/ConfigurationTest.php 
b/tests/phpunit/ConfigurationTest.php
index 598bbf4..e5adb62 100644
--- a/tests/phpunit/ConfigurationTest.php
+++ b/tests/phpunit/ConfigurationTest.php
@@ -24,13 +24,19 @@
        /**
         * Test compiling a configuration.
         *
-        * @covers MediaWikiFarm::populateSettings
         * @covers MediaWikiFarm::compileConfiguration
-        * @covers MediaWikiFarm::detectLoadingMechanism
         * @covers MediaWikiFarm::getConfiguration
         * @covers MediaWikiFarm::replaceVariables
-        * @covers MediaWikiFarm::activateExtensions
+        * @covers MediaWikiFarmConfiguration::setComposer
+        * @covers MediaWikiFarmConfiguration::setEnvironment
+        * @covers MediaWikiFarmConfiguration::getConfiguration
+        * @covers MediaWikiFarmConfiguration::populateSettings
+        * @covers MediaWikiFarmConfiguration::detectLoadingMechanism
+        * @covers MediaWikiFarmConfiguration::activateExtensions
         * @uses MediaWikiFarm::__construct
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::checkExistence
         * @uses MediaWikiFarm::checkHostVariables
@@ -41,6 +47,9 @@
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::cacheFile
         * @uses MediaWikiFarm::arrayMerge
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::getConfiguration
+        * @uses MediaWikiFarmConfiguration::setEnvironment
         * @uses AbstractMediaWikiFarmScript::rmdirr
         */
        function testHighlevelConfiguration() {
@@ -109,7 +118,8 @@
 
                $this->assertTrue( $farm->checkExistence() );
 
-               $this->assertTrue( $farm->populateSettings() );
+               $configurationObject = $farm->getConfiguration( null );
+               $this->assertTrue( $configurationObject->populateSettings() );
 
                $this->assertNull( $farm->getConfiguration( 'nonexistant' ) );
                $this->assertNull( $farm->getConfiguration( 'settings', 
'nonexistant' ) );
@@ -127,14 +137,19 @@
         * Test the different extensions/skins loading mechanisms.
         *
         * @covers MediaWikiFarm::compileConfiguration
-        * @covers MediaWikiFarm::populateSettings
-        * @covers MediaWikiFarm::activateExtensions
-        * @covers MediaWikiFarm::detectComposer
-        * @covers MediaWikiFarm::detectLoadingMechanism
-        * @covers MediaWikiFarm::setEnvironment
-        * @covers MediaWikiFarm::sortExtensions
-        * @covers MediaWikiFarm::createLocalSettings
+        * @covers MediaWikiFarmConfiguration::setComposer
+        * @covers MediaWikiFarmConfiguration::setEnvironment
+        * @covers MediaWikiFarmConfiguration::populateSettings
+        * @covers MediaWikiFarmConfiguration::activateExtensions
+        * @covers MediaWikiFarmConfiguration::detectComposer
+        * @covers MediaWikiFarmConfiguration::detectLoadingMechanism
+        * @covers MediaWikiFarmConfiguration::sortExtensions
+        * @covers MediaWikiFarmConfiguration::createLocalSettings
+        * @covers MediaWikiFarmConfiguration::setEnvironment
         * @uses MediaWikiFarm::__construct
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::compileConfiguration
         * @uses MediaWikiFarm::isLocalSettingsFresh
@@ -147,8 +162,10 @@
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::readFile
-        * @uses MediaWikiFarm::composerKey
         * @uses MediaWikiFarm::isMediaWiki
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::getConfiguration
+        * @uses MediaWikiFarmConfiguration::composerKey
         */
        function testLoadingMechanisms() {
 
@@ -214,19 +231,20 @@
         * @covers MediaWikiFarm::compileConfiguration
         * @covers MediaWikiFarm::isLocalSettingsFresh
         * @covers MediaWikiFarm::compileConfiguration
-        * @covers MediaWikiFarm::populateSettings
-        * @covers MediaWikiFarm::detectLoadingMechanism
-        * @covers MediaWikiFarm::createLocalSettings
-        * @covers MediaWikiFarm::writeArrayAssignment
         * @covers MediaWikiFarm::getConfigFile
         * @covers MediaWikiFarm::cacheFile
+        * @covers MediaWikiFarmConfiguration::setComposer
+        * @covers MediaWikiFarmConfiguration::setEnvironment
+        * @covers MediaWikiFarmConfiguration::populateSettings
+        * @covers MediaWikiFarmConfiguration::detectLoadingMechanism
+        * @covers MediaWikiFarmConfiguration::createLocalSettings
+        * @covers MediaWikiFarmConfiguration::writeArrayAssignment
         * @uses MediaWikiFarm::__construct
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::checkExistence
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::getConfiguration
         * @uses MediaWikiFarm::checkHostVariables
         * @uses MediaWikiFarm::setVersion
@@ -237,6 +255,13 @@
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::arrayMerge
         * @uses MediaWikiFarm::isMediaWiki
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::getConfiguration
+        * @uses MediaWikiFarmConfiguration::setComposer
         * @uses AbstractMediaWikiFarmScript::rmdirr
         */
        function testLoadMediaWikiConfigMultiversion() {
@@ -277,19 +302,21 @@
         * @covers MediaWikiFarm::compileConfiguration
         * @covers MediaWikiFarm::isLocalSettingsFresh
         * @covers MediaWikiFarm::compileConfiguration
-        * @covers MediaWikiFarm::populateSettings
-        * @covers MediaWikiFarm::activateExtensions
-        * @covers MediaWikiFarm::detectLoadingMechanism
-        * @covers MediaWikiFarm::createLocalSettings
-        * @covers MediaWikiFarm::writeArrayAssignment
         * @covers MediaWikiFarm::getConfigFile
         * @covers MediaWikiFarm::cacheFile
+        * @covers MediaWikiFarmConfiguration::setComposer
+        * @covers MediaWikiFarmConfiguration::setEnvironment
+        * @covers MediaWikiFarmConfiguration::activateExtensions
+        * @covers MediaWikiFarmConfiguration::populateSettings
+        * @covers MediaWikiFarmConfiguration::detectLoadingMechanism
+        * @covers MediaWikiFarmConfiguration::createLocalSettings
+        * @covers MediaWikiFarmConfiguration::writeArrayAssignment
         * @uses MediaWikiFarm::__construct
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::checkExistence
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::getConfiguration
         * @uses MediaWikiFarm::checkHostVariables
         * @uses MediaWikiFarm::setVersion
@@ -297,8 +324,14 @@
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::readFile
-        * @uses MediaWikiFarm::composerKey
         * @uses MediaWikiFarm::arrayMerge
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::getConfiguration
+        * @uses MediaWikiFarmConfiguration::setComposer
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::composerKey
         * @uses AbstractMediaWikiFarmScript::rmdirr
         */
        function testLoadMediaWikiConfigMonoversion() {
@@ -330,8 +363,13 @@
        /**
         * Test the sorting of extensions/skins.
         *
-        * @covers MediaWikiFarm::sortExtensions
+        * @covers MediaWikiFarmConfiguration::sortExtensions
+        * @covers MediaWikiFarmConfiguration::setComposer
+        * @covers MediaWikiFarmConfiguration::setEnvironment
         * @uses MediaWikiFarm::__construct
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getVariable
+        * @uses MediaWikiFarm::getConfiguration
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::checkExistence
         * @uses MediaWikiFarm::checkHostVariables
@@ -343,6 +381,7 @@
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::cacheFile
         * @uses MediaWikiFarm::isMediaWiki
+        * @uses MediaWikiFarmConfiguration::__construct
         * @uses AbstractMediaWikiFarmScript::rmdirr
         */
        function testSort() {
@@ -352,9 +391,10 @@
                        array( 'EntryPoint' => 'index.php', 'InnerMediaWiki' => 
false )
                );
                $farm->checkExistence();
+               $configuration = $farm->getConfiguration( null );
 
                $this->assertEquals( -100,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'IrrealSkinComposerForTesting', 'skin', 
'composer', 0 ),
                                array( 'FictiveSkinComposerForTesting', 'skin', 
'composer', 100 )
                        ),
@@ -362,7 +402,7 @@
                );
 
                $this->assertEquals( 1,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'UnknownExtensionComposerForTesting', 
'extension', 'composer', 100 ),
                                array( 'IrrealSkinComposerForTesting', 'skin', 
'composer', 0 )
                        ),
@@ -370,7 +410,7 @@
                );
 
                $this->assertEquals( 100,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'UnknownSkinComposerForTesting', 'skin', 
'composer', 100 ),
                                array( 'IrrealSkinComposerForTesting', 'skin', 
'composer', 0 )
                        ),
@@ -378,7 +418,7 @@
                );
 
                $this->assertEquals( 1,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'TestSkinComposer', 'skin', 'composer', 
100 ),
                                array( 'TestExtensionComposer', 'extension', 
'composer', 0 )
                        ),
@@ -386,7 +426,7 @@
                );
 
                $this->assertEquals( -1,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'TestExtensionComposer', 'extension', 
'composer', 0 ),
                                array( 'TestSkinComposer', 'skin', 'composer', 
100 )
                        ),
@@ -394,7 +434,7 @@
                );
 
                $this->assertEquals( 1,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'Wonderfun', 'extension', 
'require_once', 0 ),
                                array( 'Wonderfun', 'skin', 'require_once', 100 
)
                        ),
@@ -402,7 +442,7 @@
                );
 
                $this->assertEquals( 11,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'Wonderfun', 'extension', 
'wfLoadExtension', 0 ),
                                array( 'Wonderfun', 'skin', 'require_once', 100 
)
                        ),
@@ -410,7 +450,7 @@
                );
 
                $this->assertEquals( -100,
-                       $farm->sortExtensions(
+                       $configuration->sortExtensions(
                                array( 'Wonderfun', 'extension', 
'wfLoadExtension', 0 ),
                                array( 'Wonderful', 'extension', 
'wfLoadExtension', 100 )
                        ),
diff --git a/tests/phpunit/ConstructionTest.php 
b/tests/phpunit/ConstructionTest.php
index 703e52c..d9578f9 100644
--- a/tests/phpunit/ConstructionTest.php
+++ b/tests/phpunit/ConstructionTest.php
@@ -676,10 +676,14 @@
         *
         * @covers MediaWikiFarm::__construct
         * @covers MediaWikiFarm::selectFarm
+        * @covers MediaWikiFarm::getFarmDir
         * @covers MediaWikiFarm::getCodeDir
         * @covers MediaWikiFarm::getCacheDir
         * @covers MediaWikiFarm::getConfigFile
+        * @covers MediaWikiFarm::getConfiguration
         * @covers MediaWikiFarm::isLocalSettingsFresh
+        * @covers MediaWikiFarmConfiguration::__construct
+        * @covers MediaWikiFarmConfiguration::getConfiguration
         * @uses MediaWikiFarm::readFile
         */
        function testCheckBasicObjectPropertiesMultiversion() {
@@ -692,6 +696,9 @@
                                false,
                                array( 'EntryPoint' => 'index.php' ) );
 
+               # Check farm directory
+               $this->assertEquals( dirname( dirname( dirname( __FILE__ ) ) ), 
$farm->getFarmDir() );
+
                # Check code directory
                $this->assertEquals( self::$wgMediaWikiFarmCodeDir, 
$farm->getCodeDir() );
 
@@ -700,6 +707,17 @@
 
                # Check executable file [farm]/src/main.php
                $this->assertEquals( dirname( dirname( dirname( __FILE__ ) ) ) 
. '/src/main.php', $farm->getConfigFile() );
+
+               $this->assertEquals(
+                       array(
+                               'settings' => array(),
+                               'arrays' => array(),
+                               'extensions' => array(),
+                               'execFiles' => array(),
+                               'composer' => array(),
+                       ),
+                       $farm->getConfiguration()
+               );
        }
 
        /**
@@ -805,6 +823,9 @@
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::getVariable
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getConfiguration
+        * @uses MediaWikiFarm::getFarmConfiguration
         * @uses MediaWikiFarm::checkExistence
         * @uses MediaWikiFarm::checkHostVariables
         * @uses MediaWikiFarm::setVersion
@@ -816,14 +837,16 @@
         * @uses MediaWikiFarm::getConfigFile
         * @uses MediaWikiFarm::isLocalSettingsFresh
         * @uses MediaWikiFarm::compileConfiguration
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::sortExtensions
-        * @uses MediaWikiFarm::setEnvironment
         * @uses MediaWikiFarm::arrayMerge
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testLoadingCorrect() {
 
@@ -854,6 +877,10 @@
         * @backupGlobals enabled
         * @covers MediaWikiFarm::load
         * @uses MediaWikiFarm::__construct
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getConfiguration
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::checkExistence
@@ -862,14 +889,16 @@
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::compileConfiguration
         * @uses MediaWikiFarm::isLocalSettingsFresh
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::sortExtensions
-        * @uses MediaWikiFarm::setEnvironment
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
         * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testLoadingSoftMissingError() {
 
diff --git a/tests/phpunit/InstallationIndependantTest.php 
b/tests/phpunit/InstallationIndependantTest.php
index f9f0661..67eee32 100644
--- a/tests/phpunit/InstallationIndependantTest.php
+++ b/tests/phpunit/InstallationIndependantTest.php
@@ -404,10 +404,11 @@
        /**
         * Test the writing of the file LocalSettings.php.
         *
-        * @covers MediaWikiFarm::createLocalSettings
-        * @covers MediaWikiFarm::writeArrayAssignment
+        * @covers MediaWikiFarmConfiguration::createLocalSettings
+        * @covers MediaWikiFarmConfiguration::writeArrayAssignment
         * @uses MediaWikiFarm::__construct
         * @uses MediaWikiFarm::selectFarm
+        * @uses MediaWikiFarm::getCodeDir
         * @uses MediaWikiFarm::readFile
         */
        function testCreateLocalSettings() {
@@ -496,26 +497,30 @@
 
 PHP;
 
-               $this->assertEquals( $localSettings, 
$this->farm->createLocalSettings( $configuration, "# Pre-config\n", "# 
Post-config\n" ) );
+               $this->assertEquals( $localSettings,
+                       MediaWikiFarmConfiguration::createLocalSettings( 
$configuration, (bool) $this->farm->getCodeDir(), "# Pre-config\n", "# 
Post-config\n" )
+               );
 
                $farm = new MediaWikiFarm( 
'a.testfarm-multiversion.example.org', null, self::$wgMediaWikiFarmConfigDir, 
self::$wgMediaWikiFarmCodeDir, false );
                $extensionJson = var_export( dirname( dirname( dirname( 
__FILE__ ) ) ) . '/extension.json', true );
                $localSettings2 = str_replace( 'wfLoadExtension( 
\'MediaWikiFarm\' );', "wfLoadExtension( 'MediaWikiFarm', $extensionJson );", 
$localSettings );
-               $this->assertEquals( $localSettings2, 
$farm->createLocalSettings( $configuration, "# Pre-config\n", "# Post-config\n" 
) );
+               $this->assertEquals( $localSettings2,
+                       MediaWikiFarmConfiguration::createLocalSettings( 
$configuration, (bool) $farm->getCodeDir(), "# Pre-config\n", "# Post-config\n" 
)
+               );
        }
 
        /**
         * Test Composer key.
         *
-        * @covers MediaWikiFarm::composerKey
+        * @covers MediaWikiFarmConfiguration::composerKey
         * @uses MediaWikiFarm::__construct
         * @uses MediaWikiFarm::selectFarm
         * @uses MediaWikiFarm::readFile
         */
        function testComposerKey() {
 
-               $this->assertEquals( 'c4538db9', MediaWikiFarm::composerKey( 
'ExtensionSemanticMediaWiki' ) );
-               $this->assertEquals( '', MediaWikiFarm::composerKey( '' ) );
+               $this->assertEquals( 'c4538db9', 
MediaWikiFarmConfiguration::composerKey( 'ExtensionSemanticMediaWiki' ) );
+               $this->assertEquals( '', 
MediaWikiFarmConfiguration::composerKey( '' ) );
        }
 
        /**
diff --git a/tests/phpunit/LoadingTest.php b/tests/phpunit/LoadingTest.php
index 8f6e690..46687dc 100644
--- a/tests/phpunit/LoadingTest.php
+++ b/tests/phpunit/LoadingTest.php
@@ -71,12 +71,14 @@
         * Test regular loading mechanisms.
         *
         * @covers MediaWikiFarm::compileConfiguration
-        * @covers MediaWikiFarm::detectLoadingMechanism
         * @covers MediaWikiFarm::loadMediaWikiConfig
-        * @covers MediaWikiFarm::activateExtensions
+        * @covers MediaWikiFarmConfiguration::detectLoadingMechanism
+        * @covers MediaWikiFarmConfiguration::activateExtensions
         * @uses MediaWikiFarm::load
         * @uses MediaWikiFarm::__construct
         * @uses MediaWikiFarm::selectFarm
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getFarmConfiguration
         * @uses MediaWikiFarm::checkExistence
         * @uses MediaWikiFarm::checkHostVariables
         * @uses MediaWikiFarm::setVersion
@@ -86,19 +88,21 @@
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::compileConfiguration
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
         * @uses MediaWikiFarm::getConfigFile
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::isLocalSettingsFresh
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::arrayMerge
         * @uses MediaWikiFarm::getConfiguration
         * @uses MediaWikiFarm::getVariable
-        * @uses MediaWikiFarm::composerKey
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::composerKey
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testAllLoadingMechanisms() {
 
@@ -194,6 +198,8 @@
         * @uses MediaWikiFarm::load
         * @uses MediaWikiFarm::__construct
         * @uses MediaWikiFarm::selectFarm
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getFarmConfiguration
         * @uses MediaWikiFarm::checkExistence
         * @uses MediaWikiFarm::checkHostVariables
         * @uses MediaWikiFarm::setVersion
@@ -203,16 +209,18 @@
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::compileConfiguration
-        * @uses MediaWikiFarm::populateSettings
         * @uses MediaWikiFarm::isLocalSettingsFresh
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::setEnvironment
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::arrayMerge
         * @uses MediaWikiFarm::getConfiguration
         * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::compileConfiguration
-        * @uses MediaWikiFarm::detectLoadingMechanism
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectLoadingMechanism
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testRegistrationMediaWikiFarm() {
 
@@ -235,10 +243,12 @@
         * Test exceptions in loading mechanisms.
         *
         * @covers MediaWikiFarm::compileConfiguration
-        * @covers MediaWikiFarm::detectLoadingMechanism
+        * @covers MediaWikiFarmConfiguration::detectLoadingMechanism
         * @uses MediaWikiFarm::load
         * @uses MediaWikiFarm::__construct
         * @uses MediaWikiFarm::selectFarm
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getFarmConfiguration
         * @uses MediaWikiFarm::checkExistence
         * @uses MediaWikiFarm::checkHostVariables
         * @uses MediaWikiFarm::setVersion
@@ -248,11 +258,6 @@
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::compileConfiguration
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::isLocalSettingsFresh
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::arrayMerge
@@ -260,6 +265,13 @@
         * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testExceptionsLoadingMechanisms() {
 
diff --git a/tests/phpunit/MediaWikiFarmComposerScriptTest.php 
b/tests/phpunit/MediaWikiFarmComposerScriptTest.php
index a715e46..1b5d4f1 100644
--- a/tests/phpunit/MediaWikiFarmComposerScriptTest.php
+++ b/tests/phpunit/MediaWikiFarmComposerScriptTest.php
@@ -153,11 +153,6 @@
         * @uses MediaWikiFarm::setOtherVariables
         * @uses MediaWikiFarm::compileConfiguration
         * @uses MediaWikiFarm::isLocalSettingsFresh
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::getConfigFile
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
@@ -165,10 +160,15 @@
         * @uses MediaWikiFarm::updateVersion
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::arrayMerge
-        * @uses MediaWikiFarm::composerKey
         * @uses MediaWikiFarm::isMediaWiki
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::composerKey
         */
        function testSuccessfulLoading() {
 
diff --git a/tests/phpunit/MediaWikiFarmScriptTest.php 
b/tests/phpunit/MediaWikiFarmScriptTest.php
index 217c36e..72ab42c 100644
--- a/tests/phpunit/MediaWikiFarmScriptTest.php
+++ b/tests/phpunit/MediaWikiFarmScriptTest.php
@@ -305,20 +305,26 @@
         * @uses MediaWikiFarm::load
         * @uses MediaWikiFarm::__construct
         * @uses MediaWikiFarm::selectFarm
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getConfiguration
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
         * @uses MediaWikiFarm::checkExistence
         * @uses MediaWikiFarm::checkHostVariables
         * @uses MediaWikiFarm::compileConfiguration
         * @uses MediaWikiFarm::isLocalSettingsFresh
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testMissingHost() {
 
@@ -400,17 +406,23 @@
         * @uses MediaWikiFarm::setOtherVariables
         * @uses MediaWikiFarm::compileConfiguration
         * @uses MediaWikiFarm::isLocalSettingsFresh
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::readFile
         * @uses MediaWikiFarm::arrayMerge
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getConfiguration
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testMissingScript() {
 
@@ -454,11 +466,6 @@
         * @uses MediaWikiFarm::setOtherVariables
         * @uses MediaWikiFarm::compileConfiguration
         * @uses MediaWikiFarm::isLocalSettingsFresh
-        * @uses MediaWikiFarm::populateSettings
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::getVariable
@@ -466,6 +473,17 @@
         * @uses MediaWikiFarm::arrayMerge
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getConfiguration
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testSuccessfulLoading() {
 
@@ -525,12 +543,7 @@
         * @uses MediaWikiFarm::setVersion
         * @uses MediaWikiFarm::setOtherVariables
         * @uses MediaWikiFarm::compileConfiguration
-        * @uses MediaWikiFarm::populateSettings
         * @uses MediaWikiFarm::isLocalSettingsFresh
-        * @uses MediaWikiFarm::activateExtensions
-        * @uses MediaWikiFarm::detectComposer
-        * @uses MediaWikiFarm::setEnvironment
-        * @uses MediaWikiFarm::sortExtensions
         * @uses MediaWikiFarm::setVariable
         * @uses MediaWikiFarm::replaceVariables
         * @uses MediaWikiFarm::getVariable
@@ -538,6 +551,17 @@
         * @uses MediaWikiFarm::arrayMerge
         * @uses MediaWikiFarm::prepareLog
         * @uses MediaWikiFarm::issueLog
+        * @uses MediaWikiFarm::getConfigDir
+        * @uses MediaWikiFarm::getConfiguration
+        * @uses MediaWikiFarm::getFarmConfiguration
+        * @uses MediaWikiFarm::getVariable
+        * @uses MediaWikiFarmConfiguration::__construct
+        * @uses MediaWikiFarmConfiguration::populateSettings
+        * @uses MediaWikiFarmConfiguration::activateExtensions
+        * @uses MediaWikiFarmConfiguration::detectComposer
+        * @uses MediaWikiFarmConfiguration::setEnvironment
+        * @uses MediaWikiFarmConfiguration::sortExtensions
+        * @uses MediaWikiFarmConfiguration::getConfiguration
         */
        function testRestInPeace() {
 

-- 
To view, visit https://gerrit.wikimedia.org/r/355633
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I54d4d2739215f9cc4f59fb2671d2cd7e797d16f9
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/MediaWikiFarm
Gerrit-Branch: master
Gerrit-Owner: Seb35 <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to