Page MenuHomePhabricator

EditPage save hooks pass an entire `EditPage` object
Open, LowPublic

Description

EditPage saving can be prevented by three different hooks:

  • EditPage::attemptSave has one parameter, an EditPage object
  • EditFilter has 5 parameters:
    1. An EditPage object
    2. A string representing the new text (textbox1)
    3. A string representing the section being edited
    4. A string passed by reference to represent the hook error
    5. A string representing the summary for the edit
  • EditFilterMergedContent has 6 parameters:
    1. An IContextSource for the edit
    2. A Content object for the new page content
    3. A Status object for hooks to modify
    4. A string representing the summary for the edit
    5. A User object for the user making the edit
    6. A boolean for whether the edit is being marked as minor

After saving, but within the ::attemptSave method used by both action=edit and the api, EditPage::attemptSave:after is run with the following parameters:

  1. An EditPage object
  2. The Status object the method will return
  3. An array with the result details that can be modified

Current hook handlers assume that all four hooks will be called when an edit is saved via either action=edit or the edit api. To be able to factor out a backend, I propose that EditPage::attemptSave, EditFilter, and EditPage::attemptSave:after all be deprecated and then removed.

Deployed uses:
Both EditPage::attemptSave and EditPage::attemptSave:after are only used by WikiEditor
EditFilter is only used by SpamBlacklist and TitleBlacklist

Event Timeline

eprodromou subscribed.

OK, we need to review this in tech planning.

OK, we need to review this in tech planning.

Any updates? This will soon be blocking progress on T157658: Factor out a backend from EditPage

EditPage::attemptSave and EditPage::attemptSave::after are indeed only used by WikiEditor, and the only thing happening in there is EventLogging to EditAttemptStep schema. The perfect solution indeed would be to drop these hooks. @Ottomata is this schema still used? What is the plan (if any) for that schema and transition to new event platform? Adding Analytics as well if someone other then Andrew has an answer.

As for the two other hooks - given the new edit constraint system, it would be nice to replace them with hooks that can add more instances of IEditConstraint interface to a passed runner, or returns an array of additional constraints. However, the interface of the constrain is still not quite solidified to allow extensions implementing more of them. As it currently stands, the instance of the constraint has to get all the edit state it needs in the constructor, thus if we allow making new constraints in the hook, we need to pass significant amount of edit state into the hook... So perhaps it's better to wait on a decision regarding these 2 hooks until we have more of the constraints system migrated.

For now, the constraint system is completely internal, and until the backend is fully factored out of EditPage it should probably stay that way. I agree that the "perfect solution" is to eliminate these hooks if possible. The full migration to a backend cannot proceed until eventually the hooks passing instances of EditPage objects are removed, since the backend won't know about EditPage

Ottomata added subscribers: nettrom_WMF, nshahquinn-wmf.

Ping @nettrom_WMF and @nshahquinn-wmf as per talk:EditAttemptStep.

Pretty sure this is very active and used. We're migrating legacy schemas over to the new platform in a backwards compatible way; meaning we are doing so without changing instrumentation code. We don't have any plans to stop emitting this schema's events via that those hooks as part of that migration. Adding Product-Analytics

Yes, confirming that EditAttemptStep is still active and used frequently by the Editing team and others to track editing activity for multiple ongoing projects. I've tagged the Editing team on this task so they are aware.

daniel lowered the priority of this task from Medium to Low.Dec 2 2020, 12:14 PM

I expect that we will resolve this as part of T275847. Moving to "watching" for now, for lack of a better place.

I've excluded EditFilterMergedContent from that search because it does not pass an EditPage object and there's also a separate task for it: T304238. Then, looking at the others:

  • mediawiki-moderation's onEditFilter uses it with Reflection (!) to get the private (!!) watchthis property.
  • Athena's onEditFilter uses it to get the page being edited and then the user
  • DiscussionThreading's attemptSave uses it to get the section, the summary, and it also adds a bunch of dynamic properties that are read/written in this and other hook handlers passing an EditPage
  • Draft's onEditFilter uses it to get the main WebRequest (via EditPage::getArticle()->getContext()->getRequest()) to read a query parameter set by the extension elsewhere
  • JsonData's onEditFilter uses it to get the page
  • MsCatSelect's attemptSave uses it to append text to EditPage::$textbox1
  • SpamBlacklist's onEditFilter uses it to get the page being edited
  • SpamRegex's onEditFilter uses it to get the page, the summary, EditPage::$textbox1, and calls EditPage::spamPageWithContent()
  • TitleBlacklist's onEditFilter uses it to get the page being edited
  • WikiEditor's attemptSave uses it to get the WebRequest from the Article
  • WikiEditor's attemptSave::after uses it to get the WebRequest from the Article and also the page being edited

I think passing the page and the user would be a good starting point. Then perhaps also the summary and the new text.