Page MenuHomePhabricator

Work out how Lucas was able to save a Z6 as a Z2 and stop it from happening again
Closed, ResolvedPublic

Description

I tried to create a string object on Not Wikilambda, a test wiki with Extension:WikiLambda installed.

https://notwikilambda.toolforge.org/w/api.php
?action=edit
&format=json
&title=ZObject:Z263954
&text={"Z1K1": "Z6", "Z6K1": "a string!"}
&contentformat=application/json
&contentmodel=zobject
&token=…

The extension apparently decided to store this as a plain string (at Z28 I also tried to add labels separately but they were thrown away and the edit became a null edit):

$ curl 'https://notwikilambda.toolforge.org/w/index.php?title=ZObject:Z263954&action=raw&ctype=application/json'
"a string!"

This seems to confuse other parts of the extension:

error.log
2020-09-27 19:30:56: (mod_fastcgi.c.421) FastCGI-stderr: PHP Warning:  get_object_vars() expects parameter 1 to be object, string given in /data/project/notwikilambda/public_html/w/extensions/WikiLambda/includes/ZPersistentObject.php on line 205
2020-09-27 19:30:56: (mod_fastcgi.c.421) FastCGI-stderr: PHP Warning:  array_key_exists() expects parameter 2 to be array, null given in /data/project/notwikilambda/public_html/w/extensions/WikiLambda/includes/ZPersistentObject.php on line 206

Event Timeline

The editing UI also gets a bit confused:

Screenshot_2020-09-27 - Not Wikilambda.png (471×543 px, 31 KB)

I think the issue here is less “ZPersistentObject should learn to deal with this object” and more “this object should never have been stored in this way to begin with”. As far as the Not Wikilambda wiki goes, I’m fine with just deleting those two pages if the code is updated to ensure that further objects of this type aren’t created.

Hi Lucas - the problem is a change in the data model so that all stored objects (with a ZID, i.e. a page in the namespace) are of type Z2 - Persistent ZObject. This is assumed by the editing UI, so it was very confused to see a Z6 instead of a Z2 as the stored object. A Z6 (string) should be stored as a Z2 with key Z2K2 being the value (the string itself). So yes, probably best to just delete those two for now.

DVrandecic subscribed.

That edit shouldn't have stored in the first place. So let's check if that is still the case, and make sure this doesn't happen.

DVrandecic triaged this task as Medium priority.Oct 7 2020, 3:39 PM
Jdforrester-WMF renamed this task from PHP Warnings in ZPersistentObject.php from string object to Work out how Lucas was able to save a Z6 as a Z2 and stop it from happening again.Oct 7 2020, 3:43 PM

It’s still the case (as of commit 7fb0b72ee6 according to Special:Version) – you can use this API sandbox link to try it out (adjust the title and click “auto-fill the token” at the bottom).

Hmm, yes, replicated just now (via var api = new mw.Api(); var test = api.postWithEditToken({action:'edit',format:'json',title:'ZObject:Z12365',text:'{"Z1K1": "Z6", "Z6K1": "a T263956 string!"}', contentformat:'application/json', contentmodel:'zobject'});).

Most odd.

Change 641587 had a related patch set uploaded (by Jforrester; owner: Jforrester):
[mediawiki/extensions/WikiLambda@master] [WIP] Failing test case for bad content being written

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

hi @Jdforrester-WMF - don't we require the base persistent object always to look like {"Z1K1": "Z2", "Z2K2": (rest of object)} ? Also I'd prefer that the "Z2K1": id key always be defined and match the page name...

I.e. if you try to save an object that looks like {"Z1K1": "Z10", "Z10K1": ...} that would also fail because it's not in the persistent object format (Z2) but rather a list (Z10) at base. Or any other type that's not Z2.

hi @Jdforrester-WMF - don't we require the base persistent object always to look like {"Z1K1": "Z2", "Z2K2": (rest of object)} ? Also I'd prefer that the "Z2K1": id key always be defined and match the page name...

Yes, we require ZPersistentObject::isValid() to return true, which means that Z1K1 must be set to Z2 and Z2K2 must be set and so on. To avoid the circular update / split brain issues we've experienced on Wikibase, we're not storing the ZID inside the content, but including it when users call for the object from the external API.

This bug was an edge case in the code where things failed for the wrong reason.

Or just test a json array directly - it gets entered (because it is a valid zobject) but causes trouble because it's not a valid *persistent* zobject:

var api = new mw.Api(); var test = api.postWithEditToken({action:'edit',format:'json',title:'ZObject:Z12366', text:'["test", "test2"]', contentformat:'application/json', contentmodel:'zobject'});

Change 641587 merged by jenkins-bot:
[mediawiki/extensions/WikiLambda@master] Hooks: Prevent writing ZObjects which are JSON strings not objects

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