Allow undoing edits that change content model if top
[lhc/web/wiklou.git] / includes / content / ContentHandler.php
index 5a5c0d8..4e50c8e 100644 (file)
@@ -1,4 +1,7 @@
 <?php
+
+use MediaWiki\Search\ParserOutputSearchDataExtractor;
+
 /**
  * Base class for content handling.
  *
@@ -450,10 +453,6 @@ abstract class ContentHandler {
        public function __construct( $modelId, $formats ) {
                $this->mModelID = $modelId;
                $this->mSupportedFormats = $formats;
-
-               $this->mModelName = preg_replace( '/(Content)?Handler$/', '', get_class( $this ) );
-               $this->mModelName = preg_replace( '/[_\\\\]/', '', $this->mModelName );
-               $this->mModelName = strtolower( $this->mModelName );
        }
 
        /**
@@ -897,7 +896,7 @@ abstract class ContentHandler {
         * have it / want it.
         */
        public function getAutoDeleteReason( Title $title, &$hasHistory ) {
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
 
                // Get the last revision
                $rev = Revision::newFromTitle( $title );
@@ -1015,9 +1014,21 @@ abstract class ContentHandler {
                        return false; // no content to undo
                }
 
-               $this->checkModelID( $cur_content->getModel() );
-               $this->checkModelID( $undo_content->getModel() );
-               $this->checkModelID( $undoafter_content->getModel() );
+               try {
+                       $this->checkModelID( $cur_content->getModel() );
+                       $this->checkModelID( $undo_content->getModel() );
+                       if ( $current->getId() !== $undo->getId() ) {
+                               // 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
+                               // doing that will be confusing.
+                               $this->checkModelID( $undoafter_content->getModel() );
+                       }
+               } catch ( MWException $e ) {
+                       // If the revisions have different content models
+                       // just return false
+                       return false;
+               }
 
                if ( $cur_content->equals( $undo_content ) ) {
                        // No use doing a merge if it's just a straight revert.
@@ -1208,24 +1219,40 @@ abstract class ContentHandler {
 
        /**
         * Get fields definition for search index
+        *
+        * @todo Expose title, redirect, namespace, text, source_text, text_bytes
+        *       field mappings here. (see T142670 and T143409)
+        *
         * @param SearchEngine $engine
         * @return SearchIndexField[] List of fields this content handler can provide.
         * @since 1.28
         */
        public function getFieldsForSearchIndex( SearchEngine $engine ) {
-               /* Default fields:
-               /*
-                * namespace
-                * namespace_text
-                * redirect
-                * source_text
-                * suggest
-                * timestamp
-                * title
-                * text
-                * text_bytes
-                */
-               return [];
+               $fields['category'] = $engine->makeSearchFieldMapping(
+                       'category',
+                       SearchIndexField::INDEX_TYPE_TEXT
+               );
+
+               $fields['category']->setFlag( SearchIndexField::FLAG_CASEFOLD );
+
+               $fields['external_link'] = $engine->makeSearchFieldMapping(
+                       'external_link',
+                       SearchIndexField::INDEX_TYPE_KEYWORD
+               );
+
+               $fields['outgoing_link'] = $engine->makeSearchFieldMapping(
+                       'outgoing_link',
+                       SearchIndexField::INDEX_TYPE_KEYWORD
+               );
+
+               $fields['template'] = $engine->makeSearchFieldMapping(
+                       'template',
+                       SearchIndexField::INDEX_TYPE_KEYWORD
+               );
+
+               $fields['template']->setFlag( SearchIndexField::FLAG_CASEFOLD );
+
+               return $fields;
        }
 
        /**
@@ -1255,16 +1282,26 @@ abstract class ContentHandler {
         */
        public function getDataForSearchIndex( WikiPage $page, ParserOutput $output,
                                               SearchEngine $engine ) {
-               $fields = [];
+               $fieldData = [];
                $content = $page->getContent();
+
                if ( $content ) {
+                       $searchDataExtractor = new ParserOutputSearchDataExtractor();
+
+                       $fieldData['category'] = $searchDataExtractor->getCategories( $output );
+                       $fieldData['external_link'] = $searchDataExtractor->getExternalLinks( $output );
+                       $fieldData['outgoing_link'] = $searchDataExtractor->getOutgoingLinks( $output );
+                       $fieldData['template'] = $searchDataExtractor->getTemplates( $output );
+
                        $text = $content->getTextForSearchIndex();
-                       $fields['text'] = $text;
-                       $fields['source_text'] = $text;
-                       $fields['text_bytes'] = $content->getSize();
+
+                       $fieldData['text'] = $text;
+                       $fieldData['source_text'] = $text;
+                       $fieldData['text_bytes'] = $content->getSize();
                }
-               Hooks::run( 'SearchDataForIndex', [ &$fields, $this, $page, $output, $engine ] );
-               return $fields;
+
+               Hooks::run( 'SearchDataForIndex', [ &$fieldData, $this, $page, $output, $engine ] );
+               return $fieldData;
        }
 
        /**