[MCR] Render multi-slot diffs
[lhc/web/wiklou.git] / includes / content / ContentHandler.php
index 0a451b2..b3286a9 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
 use MediaWiki\Search\ParserOutputSearchDataExtractor;
 
@@ -613,6 +614,8 @@ abstract class ContentHandler {
 
        /**
         * Factory for creating an appropriate DifferenceEngine for this content model.
+        * Since 1.32, this is only used for page-level diffs; to diff two content objects,
+        * use getSlotDiffRenderer.
         *
         * The DifferenceEngine subclass to use is selected in getDiffEngineClass(). The
         * GetDifferenceEngine hook will receive the DifferenceEngine object and can replace or
@@ -622,6 +625,9 @@ abstract class ContentHandler {
         * the DifferenceEngine instance from the hook. If the owner of the content type wants to
         * decorare the instance, overriding this method is a safer approach.)
         *
+        * @todo This is page-level functionality so it should not belong to ContentHandler.
+        *   Move it to a better place once one exists (e.g. PageTypeHandler).
+        *
         * @since 1.21
         *
         * @param IContextSource $context Context to use, anything else will be ignored.
@@ -644,6 +650,60 @@ abstract class ContentHandler {
                return $differenceEngine;
        }
 
+       /**
+        * Get an appropriate SlotDiffRenderer for this content model.
+        * @since 1.32
+        * @param IContextSource $context
+        * @return SlotDiffRenderer
+        */
+       final public function getSlotDiffRenderer( IContextSource $context ) {
+               $slotDiffRenderer = $this->getSlotDiffRendererInternal( $context );
+               if ( get_class( $slotDiffRenderer ) === TextSlotDiffRenderer::class ) {
+                       //  To keep B/C, when SlotDiffRenderer is not overridden for a given content type
+                       // but DifferenceEngine is, use that instead.
+                       $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(
+                                       'Falling back to DifferenceEngineSlotDiffRenderer', [
+                                               'modelID' => $this->getModelID(),
+                                               'DifferenceEngine' => get_class( $differenceEngine ),
+                                       ] );
+                               $slotDiffRenderer = new DifferenceEngineSlotDiffRenderer( $differenceEngine );
+                       }
+               }
+               Hooks::run( 'GetSlotDiffRenderer', [ $this, &$slotDiffRenderer, $context ] );
+               return $slotDiffRenderer;
+       }
+
+       /**
+        * Return the SlotDiffRenderer appropriate for this content handler.
+        * @param IContextSource $context
+        * @return SlotDiffRenderer
+        */
+       protected function getSlotDiffRendererInternal( IContextSource $context ) {
+               $contentLanguage = MediaWikiServices::getInstance()->getContentLanguage();
+               $statsdDataFactory = MediaWikiServices::getInstance()->getStatsdDataFactory();
+               $slotDiffRenderer = new TextSlotDiffRenderer();
+               $slotDiffRenderer->setStatsdDataFactory( $statsdDataFactory );
+               // XXX using the page language would be better, but it's unclear how that should be injected
+               $slotDiffRenderer->setLanguage( $contentLanguage );
+               $slotDiffRenderer->setWikiDiff2MovedParagraphDetectionCutoff(
+                       $context->getConfig()->get( 'WikiDiff2MovedParagraphDetectionCutoff' )
+               );
+
+               $engine = DifferenceEngine::getEngine();
+               if ( $engine === false ) {
+                       $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_PHP );
+               } elseif ( $engine === 'wikidiff2' ) {
+                       $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_WIKIDIFF2 );
+               } else {
+                       $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_EXTERNAL, $engine );
+               }
+
+               return $slotDiffRenderer;
+       }
+
        /**
         * Get the language in which the content of the given page is written.
         *