Page MenuHomePhabricator

Fix array order for array_replace_recursive merge strategy
Closed, ResolvedPublic

Description

If a configuration array is defined in extension.json, array elements cannot currently be overridden by setting values in the corresponding configuration variable, as intended by the array_replace_recursive merge strategy. For example, if extension.json contains:

		"PageNetworkOptions": {
			"value": {
                                ...
				"groups": {
					"redlink": {
						"color": {
							"background": "lightgrey",
							"border": "grey",
						}
					}
				}
			},
			"merge_strategy": "array_replace_recursive"
		},

and LocalSettings.php contains:

$wgPageNetworkOptions = [
  'groups' => [
    'redlink' => [
      'color' => [
        'background' => 'pink'
      ]
    ]
  ]
];

the resulting configuration should have a background color of pink. But, the array elements are currently in the wrong order in ExtensionRegistry.php:

				case 'array_replace_recursive':
					$GLOBALS[$key] = array_replace_recursive( $GLOBALS[$key], $val );
					break;

so the values in extension.json have precedence rather than the values in the configuration variable. This is counter the expected behavior that a configuration variable can override values specified in extension.json.

codesearch confirms that this merge strategy is only publicly used by the JsonConfig extension, which does not provide array elements in extension.json, so this change should not affect it. This bug is preventing this merge strategy from having its intended behavior, which is preventing other extensions from being able to take advantage of this functionality.

Event Timeline

Change 693615 had a related patch set uploaded (by Cicalese; author: Cicalese):

[mediawiki/core@master] Fix array order for array_replace_recursive merge strategy

https://gerrit.wikimedia.org/r/693615

This bug is preventing this merge strategy from having its intended behavior

I still don't actually know *what* the intended behavior here is. See https://www.mediawiki.org/wiki/Manual:Extension.json/Schema#Merge_strategies which says " TODO why should this be used?"

Does array_merge_recursive not do the right thing here?

No, array_merge_recursive does not do the correct thing here. If it finds a key in both arrays, it merges the results. For the example above, array_merge_recursive would give:

'groups' => [
  'redlink' => [
    'color' => [
      'background' => [ 'ligthgrey', 'pink' ],
      'border' => 'grey'
    ]
  ]
]

but the desired result is:

'groups' => [
  'redlink' => [
    'color' => [
      'background' => 'pink',
      'border' => 'grey'
    ]
  ]
]

with 'lightgrey' replaced by 'pink', not merged with it.

For an example where this would be useful, see https://github.com/ProfessionalWiki/Network/blob/master/extension.json#L25. This allows a default JSON structure to be defined in extension.json to be passed to vis.js, where individual properties can be overridden in the site config (or per graph). A sane default is provided in extension.json but is then fully configurable per site and per graph.

Change 693615 merged by jenkins-bot:

[mediawiki/core@master] Fix array order for array_replace_recursive merge strategy

https://gerrit.wikimedia.org/r/693615

Change 696528 had a related patch set uploaded (by Reedy; author: Cicalese):

[mediawiki/core@REL1_35] Fix array order for array_replace_recursive merge strategy

https://gerrit.wikimedia.org/r/696528

Change 696529 had a related patch set uploaded (by Reedy; author: Cicalese):

[mediawiki/core@REL1_36] Fix array order for array_replace_recursive merge strategy

https://gerrit.wikimedia.org/r/696529

Change 696528 merged by jenkins-bot:

[mediawiki/core@REL1_35] Fix array order for array_replace_recursive merge strategy

https://gerrit.wikimedia.org/r/696528

Change 696529 merged by jenkins-bot:

[mediawiki/core@REL1_36] Fix array order for array_replace_recursive merge strategy

https://gerrit.wikimedia.org/r/696529

CCicalese_WMF claimed this task.
CCicalese_WMF triaged this task as Medium priority.