<?php
-
-use MediaWiki\Logger\LoggerFactory;
-use MediaWiki\MediaWikiServices;
-use MediaWiki\Search\ParserOutputSearchDataExtractor;
-
/**
* Base class for content handling.
*
*
* @author Daniel Kinzler
*/
+
+use Wikimedia\Assert\Assert;
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Revision\SlotRenderingProvider;
+use MediaWiki\Search\ParserOutputSearchDataExtractor;
+
/**
* A content handler knows how do deal with a specific type of content on a wiki
* page. Content is stored in the database in a serialized form (using a
$differenceEngine = $this->createDifferenceEngine( $context );
if ( get_class( $differenceEngine ) !== DifferenceEngine::class ) {
// TODO turn this into a deprecation warning in a later release
- LoggerFactory::getInstance( 'diff' )->notice(
+ LoggerFactory::getInstance( 'diff' )->info(
'Falling back to DifferenceEngineSlotDiffRenderer', [
'modelID' => $this->getModelID(),
'DifferenceEngine' => get_class( $differenceEngine ),
* must exist and must not be deleted.
*
* @since 1.21
+ * @since 1.32 accepts Content objects for all parameters instead of Revision objects.
+ * Passing Revision objects is deprecated.
*
- * @param Revision $current The current text
- * @param Revision $undo The revision to undo
- * @param Revision $undoafter Must be an earlier revision than $undo
+ * @param Revision|Content $current The current text
+ * @param Revision|Content $undo The content of the revision to undo
+ * @param Revision|Content $undoafter Must be from an earlier revision than $undo
+ * @param bool $undoIsLatest Set true if $undo is from the current revision (since 1.32)
*
* @return mixed Content on success, false on failure
*/
- public function getUndoContent( Revision $current, Revision $undo, Revision $undoafter ) {
- $cur_content = $current->getContent();
+ public function getUndoContent( $current, $undo, $undoafter, $undoIsLatest = false ) {
+ Assert::parameterType( Revision::class . '|' . Content::class, $current, '$current' );
+ if ( $current instanceof Content ) {
+ Assert::parameter( $undo instanceof Content, '$undo',
+ 'Must be Content when $current is Content' );
+ Assert::parameter( $undoafter instanceof Content, '$undoafter',
+ 'Must be Content when $current is Content' );
+ $cur_content = $current;
+ $undo_content = $undo;
+ $undoafter_content = $undoafter;
+ } else {
+ Assert::parameter( $undo instanceof Revision, '$undo',
+ 'Must be Revision when $current is Revision' );
+ Assert::parameter( $undoafter instanceof Revision, '$undoafter',
+ 'Must be Revision when $current is Revision' );
- if ( empty( $cur_content ) ) {
- return false; // no page
- }
+ $cur_content = $current->getContent();
+
+ if ( empty( $cur_content ) ) {
+ return false; // no page
+ }
- $undo_content = $undo->getContent();
- $undoafter_content = $undoafter->getContent();
+ $undo_content = $undo->getContent();
+ $undoafter_content = $undoafter->getContent();
- if ( !$undo_content || !$undoafter_content ) {
- return false; // no content to undo
+ if ( !$undo_content || !$undoafter_content ) {
+ return false; // no content to undo
+ }
+
+ $undoIsLatest = $current->getId() === $undo->getId();
}
try {
$this->checkModelID( $cur_content->getModel() );
$this->checkModelID( $undo_content->getModel() );
- if ( $current->getId() !== $undo->getId() ) {
+ if ( !$undoIsLatest ) {
// If we are undoing the most recent revision,
// its ok to revert content model changes. However
// if we are undoing a revision in the middle, then
* @return ParserOutput
*/
public function getParserOutputForIndexing( WikiPage $page, ParserCache $cache = null ) {
+ // TODO: MCR: ContentHandler should be called per slot, not for the whole page.
+ // See T190066.
$parserOptions = $page->makeParserOptions( 'canonical' );
- $revId = $page->getRevision()->getId();
if ( $cache ) {
$parserOutput = $cache->get( $page, $parserOptions );
}
+
if ( empty( $parserOutput ) ) {
+ $renderer = MediaWikiServices::getInstance()->getRevisionRenderer();
$parserOutput =
- $page->getContent()->getParserOutput( $page->getTitle(), $revId, $parserOptions );
+ $renderer->getRenderedRevision(
+ $page->getRevision()->getRevisionRecord(),
+ $parserOptions
+ )->getRevisionParserOutput();
if ( $cache ) {
$cache->save( $parserOutput, $page, $parserOptions );
}
return $parserOutput;
}
+ /**
+ * Returns a list of DeferrableUpdate objects for recording information about the
+ * given Content in some secondary data store.
+ *
+ * Application logic should not call this method directly. Instead, it should call
+ * DerivedPageDataUpdater::getSecondaryDataUpdates().
+ *
+ * @note Implementations must not return a LinksUpdate instance. Instead, a LinksUpdate
+ * is created by the calling code in DerivedPageDataUpdater, on the combined ParserOutput
+ * of all slots, not for each slot individually. This is in contrast to the old
+ * getSecondaryDataUpdates method defined by AbstractContent, which returned a LinksUpdate.
+ *
+ * @note Implementations should not call $content->getParserOutput, they should call
+ * $slotOutput->getSlotRendering( $role, false ) instead if they need to access a ParserOutput
+ * of $content. This allows existing ParserOutput objects to be re-used, while avoiding
+ * creating a ParserOutput when none is needed.
+ *
+ * @param Title $title The title of the page to supply the updates for
+ * @param Content $content The content to generate data updates for.
+ * @param string $role The role (slot) in which the content is being used. Which updates
+ * are performed should generally not depend on the role the content has, but the
+ * DeferrableUpdates themselves may need to know the role, to track to which slot the
+ * data refers, and to avoid overwriting data of the same kind from another slot.
+ * @param SlotRenderingProvider $slotOutput A provider that can be used to gain access to
+ * a ParserOutput of $content by calling $slotOutput->getSlotParserOutput( $role, false ).
+ * @return DeferrableUpdate[] A list of DeferrableUpdate objects for putting information
+ * about this content object somewhere. The default implementation returns an empty
+ * array.
+ * @since 1.32
+ */
+ public function getSecondaryDataUpdates(
+ Title $title,
+ Content $content,
+ $role,
+ SlotRenderingProvider $slotOutput
+ ) {
+ return [];
+ }
+
+ /**
+ * Returns a list of DeferrableUpdate objects for removing information about content
+ * in some secondary data store. This is used when a page is deleted, and also when
+ * a slot is removed from a page.
+ *
+ * Application logic should not call this method directly. Instead, it should call
+ * WikiPage::getSecondaryDataUpdates().
+ *
+ * @note Implementations must not return a LinksDeletionUpdate instance. Instead, a
+ * LinksDeletionUpdate is created by the calling code in WikiPage.
+ * This is in contrast to the old getDeletionUpdates method defined by AbstractContent,
+ * which returned a LinksUpdate.
+ *
+ * @note Implementations should not rely on the page's current content, but rather the current
+ * state of the secondary data store.
+ *
+ * @param Title $title The title of the page to supply the updates for
+ * @param string $role The role (slot) in which the content is being used. Which updates
+ * are performed should generally not depend on the role the content has, but the
+ * DeferrableUpdates themselves may need to know the role, to track to which slot the
+ * data refers, and to avoid overwriting data of the same kind from another slot.
+ *
+ * @return DeferrableUpdate[] A list of DeferrableUpdate objects for putting information
+ * about this content object somewhere. The default implementation returns an empty
+ * array.
+ *
+ * @since 1.32
+ */
+ public function getDeletionUpdates( Title $title, $role ) {
+ return [];
+ }
+
}