Quoting @Anomie from T188970#4027286:
> [We should] refactor code in core so there's one "block and log" function to both create a block and log it that can be called from AbuseFilter, Special:Block, and ApiBlock. Currently `AbuseFilter::doAbuseFilterBlock()` imperfectly duplicates code from `SpecialBlock::processForm()`, possibly because the latter is far too closely tied to the details of SpecialBlock's web UI.
# Steps
[ ] Introduce BlockUser command object (https://gerrit.wikimedia.org/r/c/mediawiki/core/+/588104)
[ ] Move all sanitizing code from SpecialBlock::processForm to SpecialBlock::onSubmit and/or create new cleaning methods
[ ] Make SpecialBlock::processForm a tiny method just calling BlockUser and deprecate that method
[ ] Migrate callers of SpecialBlock::processForm to call BlockUser instead