Multi-Content Revisions/Page Update Controller

Updating a revision is a complex process, with complicated requirements with regards to the usage of transactional logic and deferred updates. To honor these requirements, a stateful "interactor" objects are defiend in addition to the stateless storage service:

PageUpdater shall be used to create new revisions when a page is edited (or created). RevisionUpdater can be used to update derived content when some dependency (e.g. a template) changes.

Updater behavior:
 * setSlotContent will fail for any virtual slot.
 * RevisionUpdater::setSlotContent will fail for any primary.
 * $content can be set to null to explicitly remove the slot from the revision, preventing any content of that slot to be re-used from earlier revisions.
 * as indicated by the names, begin, rollback and createRevision resp updateRevision shall be used to create a transactional bracket around the calls to setSlotContent. However, no transactional behavior is guaranteed.
 * Implementations shall free any resources (such as database connections) when concluding the transaction.
 * Implementations shall take care to undo any effect any calls to setSlotContent may have had.

createRevision (resp updateRevision) would take the place of WikiPage::doEditConent. All the relevant code should be moved to PageUpdater. WikiPage::doUpdateConent should then be re-implemented based on a (global default) instance of RevisionUpdaterFactory.

TBD: can WikiPage itself act as the factory for PageUpdateController for now?

Note: Maintaining backwards compatibility for hooks may be a major challange.

TBD: it seems something like the PageUpdater is needed on two levels: a high level PageUpdater which automatically generates derived content and takes care of secondary data updates; and a low level PageUpdater which does nothing but store Content objects. It's not clear yet which component/class would be responsible for handling derived content.

Site note: the idea of derived content is tightly bound to dependency tracking: when storing derived content, we should also store what it was derived from. And when the base content changes, we need to update the derived content. Thus, dependency tracking should be implemented on the level of slots, not pages: the wikitext of a page doesn't depend on the templates it uses, but the rendered HTML of the page does.

The initial implementation of the updaters should allow the storage of additional primary and derived slots using MediaWiki's standard storage mechanism (i.e. the text table and/or the ExternalStore mechanism). The association between revisions and content blobs, along with the meta-data for each slot, is maintained in the main database, see Content Meta-Data.

Page Update Process

 * When a page is edited, the content of at least one primary slot is updated. It does not matter whether a slot with the same role existed in the previous revision.
 * One edit (user interaction) creates one revision, regardless of how many slots were updated (see also Content Meta-Data).
 * Unchanged content of primary slots is re-used from previous revisions. E.g.:
 * Revision 1 has two slots, A and B, with content ( A1, B1 )
 * Now, slot A is edited, but slot B is untouched. Then revision 2 is ( A2, B1 ). That is, slot B in revision two is the same content as slot B of revision 1.
 * Derived slots are re-calculated when primary slots change (similarly to how we already handle secondary data updates like LinksUpdate, and pre-cached data like ParserOutput).
 * TBD: should the ContentHandler of the primary slot determine which derived content is generated? If not, what component is responsible for this decision?
 * Derived content of a revision can be updated without creating a new revision.


 * SecondaryDataUpdates are created and executed for all content objects of a revision, old or new, primary or derived.