1<?php 2/** 3 * Content handler for wiki text pages. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @since 1.21 21 * 22 * @file 23 * @ingroup Content 24 */ 25 26use MediaWiki\Languages\LanguageNameUtils; 27use MediaWiki\MediaWikiServices; 28 29/** 30 * Content handler for wiki text pages. 31 * 32 * @ingroup Content 33 */ 34class WikitextContentHandler extends TextContentHandler { 35 36 public function __construct( $modelId = CONTENT_MODEL_WIKITEXT ) { 37 parent::__construct( $modelId, [ CONTENT_FORMAT_WIKITEXT ] ); 38 } 39 40 protected function getContentClass() { 41 return WikitextContent::class; 42 } 43 44 /** 45 * Returns a WikitextContent object representing a redirect to the given destination page. 46 * 47 * @param Title $destination The page to redirect to. 48 * @param string $text Text to include in the redirect, if possible. 49 * 50 * @return Content 51 * 52 * @see ContentHandler::makeRedirectContent 53 */ 54 public function makeRedirectContent( Title $destination, $text = '' ) { 55 $optionalColon = ''; 56 57 $services = MediaWikiServices::getInstance(); 58 if ( $destination->getNamespace() === NS_CATEGORY ) { 59 $optionalColon = ':'; 60 } else { 61 $iw = $destination->getInterwiki(); 62 if ( $iw && $services 63 ->getLanguageNameUtils() 64 ->getLanguageName( $iw, 65 LanguageNameUtils::AUTONYMS, 66 LanguageNameUtils::DEFINED ) 67 ) { 68 $optionalColon = ':'; 69 } 70 } 71 72 $mwRedir = $services->getMagicWordFactory()->get( 'redirect' ); 73 $redirectText = $mwRedir->getSynonym( 0 ) . 74 ' [[' . $optionalColon . $destination->getFullText() . ']]'; 75 76 if ( $text != '' ) { 77 $redirectText .= "\n" . $text; 78 } 79 80 $class = $this->getContentClass(); 81 return new $class( $redirectText ); 82 } 83 84 /** 85 * Returns true because wikitext supports redirects. 86 * 87 * @return bool Always true. 88 * 89 * @see ContentHandler::supportsRedirects 90 */ 91 public function supportsRedirects() { 92 return true; 93 } 94 95 /** 96 * Returns true because wikitext supports sections. 97 * 98 * @return bool Always true. 99 * 100 * @see ContentHandler::supportsSections 101 */ 102 public function supportsSections() { 103 return true; 104 } 105 106 /** 107 * Returns true, because wikitext supports caching using the 108 * ParserCache mechanism. 109 * 110 * @since 1.21 111 * 112 * @return bool Always true. 113 * 114 * @see ContentHandler::isParserCacheSupported 115 */ 116 public function isParserCacheSupported() { 117 return true; 118 } 119 120 /** 121 * @return FileContentHandler 122 */ 123 protected function getFileHandler() { 124 return new FileContentHandler(); 125 } 126 127 public function getFieldsForSearchIndex( SearchEngine $engine ) { 128 $fields = parent::getFieldsForSearchIndex( $engine ); 129 130 $fields['heading'] = 131 $engine->makeSearchFieldMapping( 'heading', SearchIndexField::INDEX_TYPE_TEXT ); 132 $fields['heading']->setFlag( SearchIndexField::FLAG_SCORING ); 133 134 $fields['auxiliary_text'] = 135 $engine->makeSearchFieldMapping( 'auxiliary_text', SearchIndexField::INDEX_TYPE_TEXT ); 136 137 $fields['opening_text'] = 138 $engine->makeSearchFieldMapping( 'opening_text', SearchIndexField::INDEX_TYPE_TEXT ); 139 $fields['opening_text']->setFlag( 140 SearchIndexField::FLAG_SCORING | SearchIndexField::FLAG_NO_HIGHLIGHT 141 ); 142 // Until we have full first-class content handler for files, we invoke it explicitly here 143 $fields = array_merge( $fields, $this->getFileHandler()->getFieldsForSearchIndex( $engine ) ); 144 145 return $fields; 146 } 147 148 public function getDataForSearchIndex( 149 WikiPage $page, 150 ParserOutput $parserOutput, 151 SearchEngine $engine 152 ) { 153 $fields = parent::getDataForSearchIndex( $page, $parserOutput, $engine ); 154 155 $structure = new WikiTextStructure( $parserOutput ); 156 $fields['heading'] = $structure->headings(); 157 // text fields 158 $fields['opening_text'] = $structure->getOpeningText(); 159 $fields['text'] = $structure->getMainText(); // overwrites one from ContentHandler 160 $fields['auxiliary_text'] = $structure->getAuxiliaryText(); 161 $fields['defaultsort'] = $structure->getDefaultSort(); 162 163 // Until we have full first-class content handler for files, we invoke it explicitly here 164 if ( $page->getTitle()->getNamespace() === NS_FILE ) { 165 $fields = array_merge( $fields, 166 $this->getFileHandler()->getDataForSearchIndex( $page, $parserOutput, $engine ) ); 167 } 168 return $fields; 169 } 170 171 /** 172 * Returns the content's text as-is. 173 * 174 * @param Content $content 175 * @param string|null $format The serialization format to check 176 * 177 * @return mixed 178 */ 179 public function serializeContent( Content $content, $format = null ) { 180 $this->checkFormat( $format ); 181 182 // NOTE: MessageContent also uses CONTENT_MODEL_WIKITEXT, but it's not a TextContent! 183 // Perhaps MessageContent should use a separate ContentHandler instead. 184 if ( $content instanceof MessageContent ) { 185 return $content->getMessage()->plain(); 186 } 187 188 return parent::serializeContent( $content, $format ); 189 } 190 191} 192