Page MenuHomePhabricator

Community configuration: JsonSchemaValidator fails to validate {} as an empty object
Closed, ResolvedPublic

Description

If community configuration is pointed to a nonexistent page (or to a page that has {} as its content), then the JsonSchemaValidator fails with a fatal error:

[b319f5712165bae5baddb1c1] /wiki/Special:CommunityConfiguration/FooBar InvalidArgumentException: MediaWiki\Extension\CommunityConfiguration\Validation\JsonSchemaValidator::arrayToStdClass can only process associative arrays.

Backtrace:

from /var/www/html/w/extensions/CommunityConfiguration/src/Validation/JsonSchemaValidator.php(60)
#0 /var/www/html/w/extensions/CommunityConfiguration/src/Validation/JsonSchemaValidator.php(85): MediaWiki\Extension\CommunityConfiguration\Validation\JsonSchemaValidator->arrayToStdClass()
#1 /var/www/html/w/extensions/CommunityConfiguration/src/Provider/DataProvider.php(66): MediaWiki\Extension\CommunityConfiguration\Validation\JsonSchemaValidator->validate()
#2 /var/www/html/w/extensions/CommunityConfiguration/src/Provider/DataProvider.php(85): MediaWiki\Extension\CommunityConfiguration\Provider\DataProvider->validateConfiguration()
#3 /var/www/html/w/extensions/CommunityConfiguration/src/Specials/SpecialCommunityConfigurationEditor.php(54): MediaWiki\Extension\CommunityConfiguration\Provider\DataProvider->loadValidConfigurationUncached()
#4 /var/www/html/w/extensions/CommunityConfiguration/src/Specials/SpecialCommunityConfiguration.php(45): MediaWiki\Extension\CommunityConfiguration\Specials\SpecialCommunityConfigurationEditor->execute()
#5 /var/www/html/w/includes/specialpage/SpecialPage.php(720): MediaWiki\Extension\CommunityConfiguration\Specials\SpecialCommunityConfiguration->execute()
#6 /var/www/html/w/includes/specialpage/SpecialPageFactory.php(1650): MediaWiki\SpecialPage\SpecialPage->run()
#7 /var/www/html/w/includes/actions/ActionEntryPoint.php(504): MediaWiki\SpecialPage\SpecialPageFactory->executePath()
#8 /var/www/html/w/includes/actions/ActionEntryPoint.php(145): MediaWiki\Actions\ActionEntryPoint->performRequest()
#9 /var/www/html/w/includes/MediaWikiEntryPoint.php(199): MediaWiki\Actions\ActionEntryPoint->execute()
#10 /var/www/html/w/index.php(58): MediaWiki\MediaWikiEntryPoint->run()
#11 {main}

This happens because JsonSchemaValidator does not consider {} to be an associative array. We need to special case this.

Event Timeline

Hmm... This is tricker than it looks like, as both FormatJson::decode( '{}', true ) and FormatJson::decode( '[]', true ) produce the same result, [] in PHP. From there, it appears to be impossible to determine whether [] is an empty associative or empty regular array.

We can special-case empty arrays in the validation logic, but if we keep handling it as an empty regular array (so a JSON array), we will continue having issues with empty objects. If we start handling it as an empty associative array, we will have issues with empty JSON arrays instead. Neither accepting this issue nor disallowing empty arrays seems to be acceptable.

Returning back to the list from T359623#9614934, it looks like this bug forces us to go with the third option, and use stdClass as the canonical PHP representation of the config file. This is quite a lot of changes, but I don't see any other way around this.

@Sgs Before I hop on implementing this, would you mind reviewing this and suggesting any possible alternatives that might be easier to implement?

Change 1011290 had a related patch set uploaded (by Sergio Gimeno; author: Sergio Gimeno):

[mediawiki/extensions/CommunityConfiguration@master] Use mixed type for config objects

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

@Sgs Before I hop on implementing this, would you mind reviewing this and suggesting any possible alternatives that might be easier to implement?

I was looking into alternatives but only I could come up is annotating the type of array in some way while parsing the JSON content which seemed not elegant and tedious on nested structures. Trying to forsee any blockers in proposal (3) I end-up writing a working patch for it 1011290. Happy to finish it if you think it is on the right direction.

Thanks for taking a look and uploading the patch Sergio! The patch looks good approach-wise, thanks for starting it. Reassigning it to you per your comment and the Slack discussion we had.

Change 1011290 merged by jenkins-bot:

[mediawiki/extensions/CommunityConfiguration@master] Use mixed type for config objects

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

Etonkovidova subscribed.

wiki/Special:CommunityConfiguration/nonexistent would result in the "Provider nonexistent is not found" message:

Screen Shot 2024-03-19 at 3.15.25 PM.png (1,828×610 px, 82 KB)

wiki/Special:CommunityConfiguration/nonexistent would result in the "Provider nonexistent is not found" message:

Screen Shot 2024-03-19 at 3.15.25 PM.png (1,828×610 px, 82 KB)

FWIW, this is not what changed in this task. We were having issues when the MediaWiki config page (such as MediaWiki:ExampleConfig.json) includes an empty JSON directory (so when the content of the JSON page is {}). The same issue happened when the provider existed, but an admin deleted the config JSON page.

Thx, @Urbanecm_WMF - re-checked handling incorrect json on MediaWiki:ExampleConfig.json:

contentresult
{}
Screen Shot 2024-03-21 at 1.53.59 PM.png (1,690×660 px, 140 KB)
[]
Screen Shot 2024-03-21 at 2.04.33 PM.png (3,080×476 px, 47 KB)
empty page
Screen Shot 2024-03-21 at 2.04.47 PM.png (3,124×412 px, 38 KB)