Page MenuHomePhabricator

protectionLevels says that the current title is protected if it does not exist
Open, Stalled, Needs TriagePublic


To explain the problem, I created a module with a function that returns mw.title.getCurrentTitle().protectionLevels as a string:

Steps to reproduce:

Expected result: the preview shows an empty table "[]".
Actual result: the preview shows "[move=[1=autoconfirmed, ], edit=[1=autoconfirmed, ], ]".
If the page if saved, it will have the same content until it is edited again or purged.

The bug happens only with mw.title.getCurrentTitle() and not if the title object is created with (e.g.'ThisPageDoesNotExist').protectionLevels returns [] as expected).
If I follow the same steps on the French Wiktionary, I get a different but also unexpected result, namely "[move=[1=sysop, ], edit=[1=sysop, ], ]".
On a local installation of MediaWiki + Scribunto in luastandalone mode, I get "[move=[], edit=[], ]", which seems ok.

Context: The French Wikipedia uses Module:Documentation to display documentation pages of templates. This module automatically includes the "semi-protected page" template on semi-protected pages, and this template fills a tracking category when it is included into pages that are not semi-protected. The tracking category contains many new templates that have only one revision. This seems to be related.

Event Timeline

Orlodrim created this task.Nov 29 2015, 1:09 PM
Orlodrim raised the priority of this task from to Needs Triage.
Orlodrim updated the task description. (Show Details)
Orlodrim added a subscriber: Orlodrim.
Restricted Application added subscribers: StudiesWorld, Aklapper. · View Herald TranscriptNov 29 2015, 1:09 PM
Anomie added a subscriber: Anomie.

This has nothing to do with Scribunto besides that Scribunto can be used to see it. A simpler test case, using eval.php:

$title = Title::newFromText( 'ThisDoesNotExist14' );
$wgHooks['TitleExists'][] = function ( $titleToCheck, &$exists ) use ( $title ) { if ( $titleToCheck->equals( $title ) ) { $exists = true; } };
var_dump( $title->getAllRestrictions() );

What's going on here appears to be:

  • The process of previewing the page edit sets up a "fake" revision, so self-transclusion and such work right (see T7278 and T85408, for example). Part of this "fake" revision is using the 'TitleExists' hook to fake that the page being previewed exists, since it will when the preview is saved.
  • Since the title supposedly exists, Title::loadRestrictions() loads restrictions from the page_restrictions table. Since the title doesn't have an actual page_id, it loads from page_restrictions for pr_page = 0.
  • For some reason, frwiki has entries in the page_restrictions table for pr_page = 0. frwiktionary too, and 240 other WMF wikis. That's what you're seeing here.
  • Scribunto's protectionLevels correctly reflects this incorrect protection data that was loaded for pr_page = 0.
  • To make saving after a preview faster, the preview result is saved to be reused when the page is actually saved (gerrit:177514). This is probably what makes the saved page reflect the wrong protection until edited again or purged.

I don't see any way to determine when these bogus rows might have been added. Chances are the solution is probably to DELETE FROM page_restrictions WHERE pr_page = 0 on all wikis to remove these bogus rows, and then if they start showing up again we can start looking for a cause.

Restricted Application added a subscriber: Matanya. · View Herald TranscriptNov 30 2015, 5:28 PM
Anomie set Security to None.

Thanks for digging into this.
One thing I forgot to mention: the issue does not occur with the parser function {{PROTECTIONLEVEL:edit}}.
Even if this is unrelated to scribunto, maybe the parser function does some kind of sanity checks that could be reused here?

Anomie added a comment.EditedDec 2 2015, 2:46 PM

One thing I forgot to mention: the issue does not occur with the parser function {{PROTECTIONLEVEL:edit}}.
Even if this is unrelated to scribunto, maybe the parser function does some kind of sanity checks that could be reused here?

What seems to be happening there is that {{PROTECTIONLEVEL:edit}} winds up using the Title object from the Parser, which had its restrictions loaded before the page-preview logic sets up the hooks described earlier. If you do the seemingly-equivalent {{PROTECTIONLEVEL:edit|{{FULLPAGENAME}}}} to cause it to create a new Title object, you see the bug there too.

Restricted Application added a subscriber: JEumerus. · View Herald TranscriptSep 9 2016, 3:30 AM
Od1n added a subscriber: Od1n.EditedDec 2 2017, 8:45 AM

I have just tried to reproduce this bug, and I got the expected, correct value: "[]".

Reedy changed the task status from Open to Stalled.Feb 10 2019, 1:28 AM