MediaWiki fundraising/REL1_35
ContentHandler.php
Go to the documentation of this file.
1<?php
2
29use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
36use Wikimedia\Assert\Assert;
37
59abstract class ContentHandler {
60 use ProtectedHookAccessorTrait;
61
91 public static function getContentText( Content $content = null ) {
93
94 if ( $content === null ) {
95 return '';
96 }
97
98 if ( $content instanceof TextContent ) {
99 return $content->getText();
100 }
101
102 wfDebugLog( 'ContentHandler', 'Accessing ' . $content->getModel() . ' content as text!' );
103
104 if ( $wgContentHandlerTextFallback == 'fail' ) {
105 throw new MWException(
106 "Attempt to get text from Content with model " .
107 $content->getModel()
108 );
109 }
110
111 if ( $wgContentHandlerTextFallback == 'serialize' ) {
112 return $content->serialize();
113 }
114
115 return null;
116 }
117
142 public static function makeContent( $text, Title $title = null,
143 $modelId = null, $format = null ) {
144 if ( $modelId === null ) {
145 if ( $title === null ) {
146 throw new MWException( "Must provide a Title object or a content model ID." );
147 }
148
149 $modelId = $title->getContentModel();
150 }
151
152 return MediaWikiServices::getInstance()
153 ->getContentHandlerFactory()
154 ->getContentHandler( $modelId )
155 ->unserializeContent( $text, $format );
156 }
157
194 public static function getDefaultModelFor( Title $title ) {
195 $slotRoleregistry = MediaWikiServices::getInstance()->getSlotRoleRegistry();
196 $mainSlotHandler = $slotRoleregistry->getRoleHandler( 'main' );
197 return $mainSlotHandler->getDefaultModel( $title );
198 }
199
213 public static function getForTitle( Title $title ) {
214 return MediaWikiServices::getInstance()
215 ->getContentHandlerFactory()
216 ->getContentHandler( $title->getContentModel() );
217 }
218
234 public static function getForContent( Content $content ) {
235 return MediaWikiServices::getInstance()
236 ->getContentHandlerFactory()
237 ->getContentHandler( $content->getModel() );
238 }
239
269 public static function getForModelID( $modelId ) {
270 return MediaWikiServices::getInstance()
271 ->getContentHandlerFactory()
272 ->getContentHandler( $modelId );
273 }
274
281 public static function cleanupHandlersCache() {
282 // No-op: no longer needed, since the instance cache is in the
283 // ContentHandlerFactory service, and services get reset between tests
284 }
285
299 public static function getLocalizedName( $name, Language $lang = null ) {
300 // Messages: content-model-wikitext, content-model-text,
301 // content-model-javascript, content-model-css
302 $key = "content-model-$name";
303
304 $msg = wfMessage( $key );
305 if ( $lang ) {
306 $msg->inLanguage( $lang );
307 }
308
309 return $msg->exists() ? $msg->plain() : $name;
310 }
311
320 public static function getContentModels() {
321 return MediaWikiServices::getInstance()->getContentHandlerFactory()->getContentModels();
322 }
323
332 public static function getAllContentFormats() {
333 return MediaWikiServices::getInstance()->getContentHandlerFactory()->getAllContentFormats();
334 }
335
336 // ------------------------------------------------------------------------
337
341 protected $mModelID;
342
347
359 public function __construct( $modelId, $formats ) {
360 $this->mModelID = $modelId;
361 $this->mSupportedFormats = $formats;
362 }
363
376 abstract public function serializeContent( Content $content, $format = null );
377
390 public function exportTransform( $blob, $format = null ) {
391 return $blob;
392 }
393
406 abstract public function unserializeContent( $blob, $format = null );
407
420 public function importTransform( $blob, $format = null ) {
421 return $blob;
422 }
423
433 abstract public function makeEmptyContent();
434
453 public function makeRedirectContent( Title $destination, $text = '' ) {
454 return null;
455 }
456
465 public function getModelID() {
466 return $this->mModelID;
467 }
468
477 protected function checkModelID( $model_id ) {
478 if ( $model_id !== $this->mModelID ) {
479 throw new MWException( "Bad content model: " .
480 "expected {$this->mModelID} " .
481 "but got $model_id." );
482 }
483 }
484
495 public function getSupportedFormats() {
496 return $this->mSupportedFormats;
497 }
498
511 public function getDefaultFormat() {
512 return $this->mSupportedFormats[0];
513 }
514
529 public function isSupportedFormat( $format ) {
530 if ( !$format ) {
531 return true; // this means "use the default"
532 }
533
534 return in_array( $format, $this->mSupportedFormats );
535 }
536
544 protected function checkFormat( $format ) {
545 if ( !$this->isSupportedFormat( $format ) ) {
546 throw new MWException(
547 "Format $format is not supported for content model "
548 . $this->getModelID()
549 );
550 }
551 }
552
569 public function getActionOverrides() {
570 return [];
571 }
572
600 public function createDifferenceEngine( IContextSource $context, $old = 0, $new = 0,
601 $rcid = 0, // FIXME: Deprecated, no longer used
602 $refreshCache = false, $unhide = false
603 ) {
604 $diffEngineClass = $this->getDiffEngineClass();
605 $differenceEngine = new $diffEngineClass( $context, $old, $new, $rcid, $refreshCache, $unhide );
606 $this->getHookRunner()->onGetDifferenceEngine(
607 $context, $old, $new, $refreshCache, $unhide, $differenceEngine );
608 return $differenceEngine;
609 }
610
621 final public function getSlotDiffRenderer( IContextSource $context, array $options = [] ) {
622 $slotDiffRenderer = $this->getSlotDiffRendererWithOptions( $context, $options );
623 if ( get_class( $slotDiffRenderer ) === TextSlotDiffRenderer::class ) {
624 // To keep B/C, when SlotDiffRenderer is not overridden for a given content type
625 // but DifferenceEngine is, use that instead.
626 $differenceEngine = $this->createDifferenceEngine( $context );
627 if ( get_class( $differenceEngine ) !== DifferenceEngine::class ) {
628 // TODO turn this into a deprecation warning in a later release
629 LoggerFactory::getInstance( 'diff' )->info(
630 'Falling back to DifferenceEngineSlotDiffRenderer', [
631 'modelID' => $this->getModelID(),
632 'DifferenceEngine' => get_class( $differenceEngine ),
633 ] );
634 $slotDiffRenderer = new DifferenceEngineSlotDiffRenderer( $differenceEngine );
635 }
636 }
637 $this->getHookRunner()->onGetSlotDiffRenderer( $this, $slotDiffRenderer, $context );
638 return $slotDiffRenderer;
639 }
640
647 protected function getSlotDiffRendererInternal( IContextSource $context ) {
648 return null;
649 }
650
660 protected function getSlotDiffRendererWithOptions( IContextSource $context, $options = [] ) {
661 $internalRenderer = $this->getSlotDiffRendererInternal( $context );
662 // `getSlotDiffRendererInternal` has been overriden by a class using the deprecated method.
663 // Options will not work so exit early!
664 if ( $internalRenderer !== null ) {
665 return $internalRenderer;
666 }
667
668 $contentLanguage = MediaWikiServices::getInstance()->getContentLanguage();
669 $statsdDataFactory = MediaWikiServices::getInstance()->getStatsdDataFactory();
670 $slotDiffRenderer = new TextSlotDiffRenderer();
671 $slotDiffRenderer->setStatsdDataFactory( $statsdDataFactory );
672 // XXX using the page language would be better, but it's unclear how that should be injected
673 $slotDiffRenderer->setLanguage( $contentLanguage );
674
675 $inline = ( $options['diff-type'] ?? '' ) === 'inline';
676 $engine = 'wikidiff2';
677 $engine = DifferenceEngine::getEngine();
678
679 if ( $engine === 'php' ) {
680 $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_PHP );
681 } elseif ( $engine === 'wikidiff2' ) {
682 if ( $inline ) {
683 $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_WIKIDIFF2_INLINE );
684 } else {
685 $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_WIKIDIFF2 );
686 }
687 } else {
688 $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_EXTERNAL, $engine );
689 }
690
691 return $slotDiffRenderer;
692 }
693
714 public function getPageLanguage( Title $title, Content $content = null ) {
715 global $wgLang;
716 $services = MediaWikiServices::getInstance();
717 $pageLang = $services->getContentLanguage();
718
719 if ( $title->inNamespace( NS_MEDIAWIKI ) ) {
720 // Parse mediawiki messages with correct target language
721 list( /* $unused */, $lang ) = $services->getMessageCache()->figureMessage( $title->getText() );
722 $pageLang = $services->getLanguageFactory()->getLanguage( $lang );
723 }
724
725 // Simplify hook handlers by only passing objects of one type, in case nothing
726 // else has unstubbed the StubUserLang object by now.
727 StubObject::unstub( $wgLang );
728
729 $this->getHookRunner()->onPageContentLanguage( $title, $pageLang, $wgLang );
730
731 return wfGetLangObj( $pageLang );
732 }
733
755 public function getPageViewLanguage( Title $title, Content $content = null ) {
756 $pageLang = $this->getPageLanguage( $title, $content );
757
758 if ( $title->getNamespace() !== NS_MEDIAWIKI ) {
759 // If the user chooses a variant, the content is actually
760 // in a language whose code is the variant code.
761 $variant = $this->getLanguageConverter( $pageLang )->getPreferredVariant();
762 if ( $pageLang->getCode() !== $variant ) {
763 $pageLang = MediaWikiServices::getInstance()->getLanguageFactory()
764 ->getLanguage( $variant );
765 }
766 }
767
768 return $pageLang;
769 }
770
791 public function canBeUsedOn( Title $title ) {
792 $ok = true;
793
794 $this->getHookRunner()->onContentModelCanBeUsedOn( $this->getModelID(), $title, $ok );
795
796 return $ok;
797 }
798
807 protected function getDiffEngineClass() {
808 return DifferenceEngine::class;
809 }
810
826 public function merge3( Content $oldContent, Content $myContent, Content $yourContent ) {
827 return false;
828 }
829
835 private function getLanguageConverter( $language ) : ILanguageConverter {
836 return MediaWikiServices::getInstance()->getLanguageConverterFactory()
837 ->getLanguageConverter( $language );
838 }
839
852 private function getChangeType(
853 Content $oldContent = null,
854 Content $newContent = null,
855 $flags = 0
856 ) {
857 $oldTarget = $oldContent !== null ? $oldContent->getRedirectTarget() : null;
858 $newTarget = $newContent !== null ? $newContent->getRedirectTarget() : null;
859
860 // We check for the type of change in the given edit, and return string key accordingly
861
862 // Blanking of a page
863 if ( $oldContent && $oldContent->getSize() > 0 &&
864 $newContent && $newContent->getSize() === 0
865 ) {
866 return 'blank';
867 }
868
869 // Redirects
870 if ( $newTarget ) {
871 if ( !$oldTarget ) {
872 // New redirect page (by creating new page or by changing content page)
873 return 'new-redirect';
874 } elseif ( !$newTarget->equals( $oldTarget ) ||
875 $oldTarget->getFragment() !== $newTarget->getFragment()
876 ) {
877 // Redirect target changed
878 return 'changed-redirect-target';
879 }
880 } elseif ( $oldTarget ) {
881 // Changing an existing redirect into a non-redirect
882 return 'removed-redirect';
883 }
884
885 // New page created
886 if ( $flags & EDIT_NEW && $newContent ) {
887 if ( $newContent->getSize() === 0 ) {
888 // New blank page
889 return 'newblank';
890 } else {
891 return 'newpage';
892 }
893 }
894
895 // Removing more than 90% of the page
896 if ( $oldContent && $newContent && $oldContent->getSize() > 10 * $newContent->getSize() ) {
897 return 'replace';
898 }
899
900 // Content model changed
901 if ( $oldContent && $newContent && $oldContent->getModel() !== $newContent->getModel() ) {
902 return 'contentmodelchange';
903 }
904
905 return null;
906 }
907
920 public function getAutosummary(
921 Content $oldContent = null,
922 Content $newContent = null,
923 $flags = 0
924 ) {
925 $changeType = $this->getChangeType( $oldContent, $newContent, $flags );
926
927 // There's no applicable auto-summary for our case, so our auto-summary is empty.
928 if ( !$changeType ) {
929 return '';
930 }
931
932 // Decide what kind of auto-summary is needed.
933 switch ( $changeType ) {
934 case 'new-redirect':
935 $newTarget = $newContent->getRedirectTarget();
936 $truncatedtext = $newContent->getTextForSummary(
937 250
938 - strlen( wfMessage( 'autoredircomment' )->inContentLanguage()->text() )
939 - strlen( $newTarget->getFullText() )
940 );
941
942 return wfMessage( 'autoredircomment', $newTarget->getFullText() )
943 ->plaintextParams( $truncatedtext )->inContentLanguage()->text();
944 case 'changed-redirect-target':
945 $oldTarget = $oldContent->getRedirectTarget();
946 $newTarget = $newContent->getRedirectTarget();
947
948 $truncatedtext = $newContent->getTextForSummary(
949 250
950 - strlen( wfMessage( 'autosumm-changed-redirect-target' )
951 ->inContentLanguage()->text() )
952 - strlen( $oldTarget->getFullText() )
953 - strlen( $newTarget->getFullText() )
954 );
955
956 return wfMessage( 'autosumm-changed-redirect-target',
957 $oldTarget->getFullText(),
958 $newTarget->getFullText() )
959 ->rawParams( $truncatedtext )->inContentLanguage()->text();
960 case 'removed-redirect':
961 $oldTarget = $oldContent->getRedirectTarget();
962 $truncatedtext = $newContent->getTextForSummary(
963 250
964 - strlen( wfMessage( 'autosumm-removed-redirect' )
965 ->inContentLanguage()->text() )
966 - strlen( $oldTarget->getFullText() ) );
967
968 return wfMessage( 'autosumm-removed-redirect', $oldTarget->getFullText() )
969 ->rawParams( $truncatedtext )->inContentLanguage()->text();
970 case 'newpage':
971 // If they're making a new article, give its text, truncated, in the summary.
972 $truncatedtext = $newContent->getTextForSummary(
973 200 - strlen( wfMessage( 'autosumm-new' )->inContentLanguage()->text() ) );
974
975 return wfMessage( 'autosumm-new' )->rawParams( $truncatedtext )
976 ->inContentLanguage()->text();
977 case 'blank':
978 return wfMessage( 'autosumm-blank' )->inContentLanguage()->text();
979 case 'replace':
980 $truncatedtext = $newContent->getTextForSummary(
981 200 - strlen( wfMessage( 'autosumm-replace' )->inContentLanguage()->text() ) );
982
983 return wfMessage( 'autosumm-replace' )->rawParams( $truncatedtext )
984 ->inContentLanguage()->text();
985 case 'newblank':
986 return wfMessage( 'autosumm-newblank' )->inContentLanguage()->text();
987 default:
988 return '';
989 }
990 }
991
1004 public function getChangeTag(
1005 Content $oldContent = null,
1006 Content $newContent = null,
1007 $flags = 0
1008 ) {
1009 $changeType = $this->getChangeType( $oldContent, $newContent, $flags );
1010
1011 // There's no applicable tag for this change.
1012 if ( !$changeType ) {
1013 return null;
1014 }
1015
1016 // Core tags use the same keys as ones returned from $this->getChangeType()
1017 // but prefixed with pseudo namespace 'mw-', so we add the prefix before checking
1018 // if this type of change should be tagged
1019 $tag = 'mw-' . $changeType;
1020
1021 // Not all change types are tagged, so we check against the list of defined tags.
1022 if ( in_array( $tag, ChangeTags::getSoftwareTags() ) ) {
1023 return $tag;
1024 }
1025
1026 return null;
1027 }
1028
1045 public function getAutoDeleteReason( Title $title, &$hasHistory ) {
1046 $dbr = wfGetDB( DB_REPLICA );
1047 $revLookup = MediaWikiServices::getInstance()->getRevisionLookup();
1048
1049 // Get the last revision
1050 $revRecord = $revLookup->getRevisionByTitle( $title );
1051
1052 if ( $revRecord === null ) {
1053 return false;
1054 }
1055
1056 // Get the article's contents
1057 $content = $revRecord->getContent( SlotRecord::MAIN );
1058 $blank = false;
1059
1060 // If the page is blank, use the text from the previous revision,
1061 // which can only be blank if there's a move/import/protect dummy
1062 // revision involved
1063 if ( !$content || $content->isEmpty() ) {
1064 $prev = $revLookup->getPreviousRevision( $revRecord );
1065
1066 if ( $prev ) {
1067 $revRecord = $prev;
1068 $content = $prev->getContent( SlotRecord::MAIN );
1069 $blank = true;
1070 }
1071 }
1072
1073 $this->checkModelID( $revRecord->getSlot( SlotRecord::MAIN )->getModel() );
1074
1075 // Find out if there was only one contributor
1076 // Only scan the last 20 revisions
1077 $revQuery = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo();
1078 $res = $dbr->select(
1079 $revQuery['tables'],
1080 [ 'rev_user_text' => $revQuery['fields']['rev_user_text'] ],
1081 [
1082 'rev_page' => $title->getArticleID(),
1083 $dbr->bitAnd( 'rev_deleted', RevisionRecord::DELETED_USER ) . ' = 0'
1084 ],
1085 __METHOD__,
1086 [ 'LIMIT' => 20 ],
1087 $revQuery['joins']
1088 );
1089
1090 if ( $res === false ) {
1091 // This page has no revisions, which is very weird
1092 return false;
1093 }
1094
1095 $hasHistory = ( $res->numRows() > 1 );
1096 $row = $dbr->fetchObject( $res );
1097
1098 if ( $row ) { // $row is false if the only contributor is hidden
1099 $onlyAuthor = $row->rev_user_text;
1100 // Try to find a second contributor
1101 foreach ( $res as $row ) {
1102 if ( $row->rev_user_text != $onlyAuthor ) { // T24999
1103 $onlyAuthor = false;
1104 break;
1105 }
1106 }
1107 } else {
1108 $onlyAuthor = false;
1109 }
1110
1111 // Generate the summary with a '$1' placeholder
1112 if ( $blank ) {
1113 // The current revision is blank and the one before is also
1114 // blank. It's just not our lucky day
1115 $reason = wfMessage( 'exbeforeblank', '$1' )->inContentLanguage()->text();
1116 } else {
1117 if ( $onlyAuthor ) {
1118 $reason = wfMessage(
1119 'excontentauthor',
1120 '$1',
1121 $onlyAuthor
1122 )->inContentLanguage()->text();
1123 } else {
1124 $reason = wfMessage( 'excontent', '$1' )->inContentLanguage()->text();
1125 }
1126 }
1127
1128 if ( $reason == '-' ) {
1129 // Allow these UI messages to be blanked out cleanly
1130 return '';
1131 }
1132
1133 // Max content length = max comment length - length of the comment (excl. $1)
1134 $maxLength = CommentStore::COMMENT_CHARACTER_LIMIT - ( strlen( $reason ) - 2 );
1135 $text = $content ? $content->getTextForSummary( $maxLength ) : '';
1136
1137 // Now replace the '$1' placeholder
1138 $reason = str_replace( '$1', $text, $reason );
1139
1140 return $reason;
1141 }
1142
1163 public function getUndoContent( $current, $undo, $undoafter, $undoIsLatest = false ) {
1164 Assert::parameterType( Revision::class . '|' . Content::class, $current, '$current' );
1165 if ( $current instanceof Content ) {
1166 Assert::parameter( $undo instanceof Content, '$undo',
1167 'Must be Content when $current is Content' );
1168 Assert::parameter( $undoafter instanceof Content, '$undoafter',
1169 'Must be Content when $current is Content' );
1170 $cur_content = $current;
1171 $undo_content = $undo;
1172 $undoafter_content = $undoafter;
1173 } else {
1174 Assert::parameter( $undo instanceof Revision, '$undo',
1175 'Must be Revision when $current is Revision' );
1176 Assert::parameter( $undoafter instanceof Revision, '$undoafter',
1177 'Must be Revision when $current is Revision' );
1178
1179 wfDeprecated( __METHOD__ . ' with Revision objects', '1.32' );
1180
1181 $cur_content = $current->getContent();
1182
1183 if ( empty( $cur_content ) ) {
1184 return false; // no page
1185 }
1186
1187 $undo_content = $undo->getContent();
1188 $undoafter_content = $undoafter->getContent();
1189
1190 if ( !$undo_content || !$undoafter_content ) {
1191 return false; // no content to undo
1192 }
1193
1194 $undoIsLatest = $current->getId() === $undo->getId();
1195 }
1196
1197 try {
1198 $this->checkModelID( $cur_content->getModel() );
1199 $this->checkModelID( $undo_content->getModel() );
1200 if ( !$undoIsLatest ) {
1201 // If we are undoing the most recent revision,
1202 // its ok to revert content model changes. However
1203 // if we are undoing a revision in the middle, then
1204 // doing that will be confusing.
1205 $this->checkModelID( $undoafter_content->getModel() );
1206 }
1207 } catch ( MWException $e ) {
1208 // If the revisions have different content models
1209 // just return false
1210 return false;
1211 }
1212
1213 if ( $cur_content->equals( $undo_content ) ) {
1214 // No use doing a merge if it's just a straight revert.
1215 return $undoafter_content;
1216 }
1217
1218 $undone_content = $this->merge3( $undo_content, $undoafter_content, $cur_content );
1219
1220 return $undone_content;
1221 }
1222
1232 public function isParserCacheSupported() {
1233 return false;
1234 }
1235
1247 public function supportsSections() {
1248 return false;
1249 }
1250
1259 public function supportsCategories() {
1260 return true;
1261 }
1262
1274 public function supportsRedirects() {
1275 return false;
1276 }
1277
1285 public function supportsDirectEditing() {
1286 return false;
1287 }
1288
1296 public function supportsDirectApiEditing() {
1297 return $this->supportsDirectEditing();
1298 }
1299
1312 public function getFieldsForSearchIndex( SearchEngine $engine ) {
1313 $fields = [];
1314 $fields['category'] = $engine->makeSearchFieldMapping(
1315 'category',
1316 SearchIndexField::INDEX_TYPE_TEXT
1317 );
1318 $fields['category']->setFlag( SearchIndexField::FLAG_CASEFOLD );
1319
1320 $fields['external_link'] = $engine->makeSearchFieldMapping(
1321 'external_link',
1322 SearchIndexField::INDEX_TYPE_KEYWORD
1323 );
1324
1325 $fields['outgoing_link'] = $engine->makeSearchFieldMapping(
1326 'outgoing_link',
1327 SearchIndexField::INDEX_TYPE_KEYWORD
1328 );
1329
1330 $fields['template'] = $engine->makeSearchFieldMapping(
1331 'template',
1332 SearchIndexField::INDEX_TYPE_KEYWORD
1333 );
1334 $fields['template']->setFlag( SearchIndexField::FLAG_CASEFOLD );
1335
1336 $fields['content_model'] = $engine->makeSearchFieldMapping(
1337 'content_model',
1338 SearchIndexField::INDEX_TYPE_KEYWORD
1339 );
1340
1341 return $fields;
1342 }
1343
1353 protected function addSearchField( &$fields, SearchEngine $engine, $name, $type ) {
1354 $fields[$name] = $engine->makeSearchFieldMapping( $name, $type );
1355 return $fields;
1356 }
1357
1371 public function getDataForSearchIndex(
1372 WikiPage $page,
1373 ParserOutput $output,
1374 SearchEngine $engine
1375 ) {
1376 $fieldData = [];
1377 $content = $page->getContent();
1378
1379 if ( $content ) {
1380 $searchDataExtractor = new ParserOutputSearchDataExtractor();
1381
1382 $fieldData['category'] = $searchDataExtractor->getCategories( $output );
1383 $fieldData['external_link'] = $searchDataExtractor->getExternalLinks( $output );
1384 $fieldData['outgoing_link'] = $searchDataExtractor->getOutgoingLinks( $output );
1385 $fieldData['template'] = $searchDataExtractor->getTemplates( $output );
1386
1387 $text = $content->getTextForSearchIndex();
1388
1389 $fieldData['text'] = $text;
1390 $fieldData['source_text'] = $text;
1391 $fieldData['text_bytes'] = $content->getSize();
1392 $fieldData['content_model'] = $content->getModel();
1393 }
1394
1395 $this->getHookRunner()->onSearchDataForIndex( $fieldData, $this, $page, $output, $engine );
1396 return $fieldData;
1397 }
1398
1410 public function getParserOutputForIndexing( WikiPage $page, ParserCache $cache = null ) {
1411 // TODO: MCR: ContentHandler should be called per slot, not for the whole page.
1412 // See T190066.
1413 $parserOptions = $page->makeParserOptions( 'canonical' );
1414 if ( $cache ) {
1415 $parserOutput = $cache->get( $page, $parserOptions );
1416 }
1417
1418 if ( empty( $parserOutput ) ) {
1419 $renderer = MediaWikiServices::getInstance()->getRevisionRenderer();
1420 $revisionRecord = $this->latestRevision( $page );
1421 $parserOutput =
1422 $renderer->getRenderedRevision(
1423 $revisionRecord,
1424 $parserOptions
1425 )->getRevisionParserOutput();
1426 if ( $cache ) {
1427 $cache->save( $parserOutput, $page, $parserOptions );
1428 }
1429 }
1430 return $parserOutput;
1431 }
1432
1433 private function latestRevision( WikiPage $page ): RevisionRecord {
1434 $revRecord = $page->getRevisionRecord();
1435 if ( $revRecord == null ) {
1436 // If the content represents a brand new page it's possible
1437 // we need to fetch it from the master.
1438 $page->loadPageData( WikiPage::READ_LATEST );
1439 $revRecord = $page->getRevisionRecord();
1440 if ( $revRecord == null ) {
1441 $text = $page->getTitle()->getPrefixedText();
1442 throw new MWException(
1443 "No revision could be loaded for page: $text" );
1444 }
1445 }
1446
1447 return $revRecord;
1448 }
1449
1483 Title $title,
1485 $role,
1486 SlotRenderingProvider $slotOutput
1487 ) {
1488 return [];
1489 }
1490
1521 public function getDeletionUpdates( Title $title, $role ) {
1522 return [];
1523 }
1524
1525}
$wgContentHandlerTextFallback
How to react if a plain text version of a non-text Content object is requested using ContentHandler::...
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
$wgLang
Definition Setup.php:781
return[ 'abap'=> true, 'abl'=> true, 'abnf'=> true, 'aconf'=> true, 'actionscript'=> true, 'actionscript3'=> true, 'ada'=> true, 'ada2005'=> true, 'ada95'=> true, 'adl'=> true, 'agda'=> true, 'aheui'=> true, 'ahk'=> true, 'alloy'=> true, 'ambienttalk'=> true, 'ambienttalk/2'=> true, 'ampl'=> true, 'antlr'=> true, 'antlr-actionscript'=> true, 'antlr-as'=> true, 'antlr-c#'=> true, 'antlr-cpp'=> true, 'antlr-csharp'=> true, 'antlr-java'=> true, 'antlr-objc'=> true, 'antlr-perl'=> true, 'antlr-python'=> true, 'antlr-rb'=> true, 'antlr-ruby'=> true, 'apache'=> true, 'apacheconf'=> true, 'apl'=> true, 'applescript'=> true, 'arduino'=> true, 'arexx'=> true, 'arrow'=> true, 'as'=> true, 'as3'=> true, 'asm'=> true, 'aspectj'=> true, 'aspx-cs'=> true, 'aspx-vb'=> true, 'asy'=> true, 'asymptote'=> true, 'at'=> true, 'augeas'=> true, 'autohotkey'=> true, 'autoit'=> true, 'awk'=> true, 'b3d'=> true, 'bare'=> true, 'basemake'=> true, 'bash'=> true, 'basic'=> true, 'bat'=> true, 'batch'=> true, 'bbcbasic'=> true, 'bbcode'=> true, 'bc'=> true, 'befunge'=> true, 'bf'=> true, 'bib'=> true, 'bibtex'=> true, 'blitzbasic'=> true, 'blitzmax'=> true, 'bmax'=> true, 'bnf'=> true, 'boa'=> true, 'boo'=> true, 'boogie'=> true, 'bplus'=> true, 'brainfuck'=> true, 'bro'=> true, 'bsdmake'=> true, 'bst'=> true, 'bst-pybtex'=> true, 'bugs'=> true, 'c'=> true, 'c#'=> true, 'c++'=> true, 'c++-objdumb'=> true, 'c-objdump'=> true, 'ca65'=> true, 'cadl'=> true, 'camkes'=> true, 'capdl'=> true, 'capnp'=> true, 'cbmbas'=> true, 'ceylon'=> true, 'cf3'=> true, 'cfc'=> true, 'cfengine3'=> true, 'cfg'=> true, 'cfm'=> true, 'cfs'=> true, 'chai'=> true, 'chaiscript'=> true, 'chapel'=> true, 'charmci'=> true, 'cheetah'=> true, 'chpl'=> true, 'cirru'=> true, 'cl'=> true, 'clay'=> true, 'clean'=> true, 'clipper'=> true, 'clj'=> true, 'cljs'=> true, 'clojure'=> true, 'clojurescript'=> true, 'cmake'=> true, 'cobol'=> true, 'cobolfree'=> true, 'coffee'=> true, 'coffee-script'=> true, 'coffeescript'=> true, 'common-lisp'=> true, 'componentpascal'=> true, 'console'=> true, 'control'=> true, 'coq'=> true, 'cp'=> true, 'cpp'=> true, 'cpp-objdump'=> true, 'cpsa'=> true, 'cr'=> true, 'crmsh'=> true, 'croc'=> true, 'cry'=> true, 'cryptol'=> true, 'crystal'=> true, 'csh'=> true, 'csharp'=> true, 'csound'=> true, 'csound-csd'=> true, 'csound-document'=> true, 'csound-orc'=> true, 'csound-sco'=> true, 'csound-score'=> true, 'css'=> true, 'css+django'=> true, 'css+erb'=> true, 'css+genshi'=> true, 'css+genshitext'=> true, 'css+jinja'=> true, 'css+lasso'=> true, 'css+mako'=> true, 'css+mozpreproc'=> true, 'css+myghty'=> true, 'css+php'=> true, 'css+ruby'=> true, 'css+smarty'=> true, 'cu'=> true, 'cucumber'=> true, 'cuda'=> true, 'cxx-objdump'=> true, 'cypher'=> true, 'cython'=> true, 'd'=> true, 'd-objdump'=> true, 'dart'=> true, 'dasm16'=> true, 'debcontrol'=> true, 'debsources'=> true, 'delphi'=> true, 'devicetree'=> true, 'dg'=> true, 'diff'=> true, 'django'=> true, 'dmesg'=> true, 'do'=> true, 'docker'=> true, 'dockerfile'=> true, 'dosbatch'=> true, 'doscon'=> true, 'dosini'=> true, 'dpatch'=> true, 'dtd'=> true, 'dts'=> true, 'duby'=> true, 'duel'=> true, 'dylan'=> true, 'dylan-console'=> true, 'dylan-lid'=> true, 'dylan-repl'=> true, 'earl-grey'=> true, 'earlgrey'=> true, 'easytrieve'=> true, 'ebnf'=> true, 'ec'=> true, 'ecl'=> true, 'eg'=> true, 'eiffel'=> true, 'elisp'=> true, 'elixir'=> true, 'elm'=> true, 'emacs'=> true, 'emacs-lisp'=> true, 'email'=> true, 'eml'=> true, 'erb'=> true, 'erl'=> true, 'erlang'=> true, 'evoque'=> true, 'ex'=> true, 'execline'=> true, 'exs'=> true, 'extempore'=> true, 'ezhil'=> true, 'f#'=> true, 'factor'=> true, 'fan'=> true, 'fancy'=> true, 'felix'=> true, 'fennel'=> true, 'fish'=> true, 'fishshell'=> true, 'flatline'=> true, 'flo'=> true, 'floscript'=> true, 'flx'=> true, 'fnl'=> true, 'forth'=> true, 'fortran'=> true, 'fortranfixed'=> true, 'foxpro'=> true, 'freefem'=> true, 'fsharp'=> true, 'fstar'=> true, 'fy'=> true, 'gap'=> true, 'gas'=> true, 'gawk'=> true, 'gd'=> true, 'gdscript'=> true, 'genshi'=> true, 'genshitext'=> true, 'gherkin'=> true, 'glsl'=> true, 'gnuplot'=> true, 'go'=> true, 'golo'=> true, 'gooddata-cl'=> true, 'gosu'=> true, 'groff'=> true, 'groovy'=> true, 'gst'=> true, 'haml'=> true, 'handlebars'=> true, 'haskell'=> true, 'haxe'=> true, 'haxeml'=> true, 'hexdump'=> true, 'hlsl'=> true, 'hs'=> true, 'hsa'=> true, 'hsail'=> true, 'hspec'=> true, 'html'=> true, 'html+cheetah'=> true, 'html+django'=> true, 'html+erb'=> true, 'html+evoque'=> true, 'html+genshi'=> true, 'html+handlebars'=> true, 'html+jinja'=> true, 'html+kid'=> true, 'html+lasso'=> true, 'html+mako'=> true, 'html+myghty'=> true, 'html+ng2'=> true, 'html+php'=> true, 'html+ruby'=> true, 'html+smarty'=> true, 'html+spitfire'=> true, 'html+twig'=> true, 'html+velocity'=> true, 'htmlcheetah'=> true, 'htmldjango'=> true, 'http'=> true, 'hx'=> true, 'hxml'=> true, 'hxsl'=> true, 'hy'=> true, 'hybris'=> true, 'hylang'=> true, 'i6'=> true, 'i6t'=> true, 'i7'=> true, 'icon'=> true, 'idl'=> true, 'idl4'=> true, 'idr'=> true, 'idris'=> true, 'iex'=> true, 'igor'=> true, 'igorpro'=> true, 'ik'=> true, 'inform6'=> true, 'inform7'=> true, 'ini'=> true, 'io'=> true, 'ioke'=> true, 'irb'=> true, 'irc'=> true, 'isabelle'=> true, 'j'=> true, 'jade'=> true, 'jags'=> true, 'jasmin'=> true, 'jasminxt'=> true, 'java'=> true, 'javascript'=> true, 'javascript+cheetah'=> true, 'javascript+django'=> true, 'javascript+erb'=> true, 'javascript+genshi'=> true, 'javascript+genshitext'=> true, 'javascript+jinja'=> true, 'javascript+lasso'=> true, 'javascript+mako'=> true, 'javascript+mozpreproc'=> true, 'javascript+myghty'=> true, 'javascript+php'=> true, 'javascript+ruby'=> true, 'javascript+smarty'=> true, 'javascript+spitfire'=> true, 'jbst'=> true, 'jcl'=> true, 'jinja'=> true, 'jl'=> true, 'jlcon'=> true, 'jproperties'=> true, 'js'=> true, 'js+cheetah'=> true, 'js+django'=> true, 'js+erb'=> true, 'js+genshi'=> true, 'js+genshitext'=> true, 'js+jinja'=> true, 'js+lasso'=> true, 'js+mako'=> true, 'js+myghty'=> true, 'js+php'=> true, 'js+ruby'=> true, 'js+smarty'=> true, 'js+spitfire'=> true, 'jsgf'=> true, 'json'=> true, 'json-ld'=> true, 'json-object'=> true, 'jsonld'=> true, 'jsonml+bst'=> true, 'jsp'=> true, 'julia'=> true, 'juttle'=> true, 'kal'=> true, 'kconfig'=> true, 'kernel-config'=> true, 'kid'=> true, 'kmsg'=> true, 'koka'=> true, 'kotlin'=> true, 'ksh'=> true, 'lagda'=> true, 'lasso'=> true, 'lassoscript'=> true, 'latex'=> true, 'lcry'=> true, 'lcryptol'=> true, 'lean'=> true, 'less'=> true, 'lhaskell'=> true, 'lhs'=> true, 'lid'=> true, 'lidr'=> true, 'lidris'=> true, 'lighttpd'=> true, 'lighty'=> true, 'limbo'=> true, 'linux-config'=> true, 'liquid'=> true, 'lisp'=> true, 'literate-agda'=> true, 'literate-cryptol'=> true, 'literate-haskell'=> true, 'literate-idris'=> true, 'live-script'=> true, 'livescript'=> true, 'llvm'=> true, 'llvm-mir'=> true, 'llvm-mir-body'=> true, 'logos'=> true, 'logtalk'=> true, 'lsl'=> true, 'lua'=> true, 'm2'=> true, 'make'=> true, 'makefile'=> true, 'mako'=> true, 'man'=> true, 'maql'=> true, 'mask'=> true, 'mason'=> true, 'mathematica'=> true, 'matlab'=> true, 'matlabsession'=> true, 'mawk'=> true, 'md'=> true, 'menuconfig'=> true, 'mf'=> true, 'mime'=> true, 'minid'=> true, 'miniscript'=> true, 'mma'=> true, 'modelica'=> true, 'modula2'=> true, 'moin'=> true, 'monkey'=> true, 'monte'=> true, 'moo'=> true, 'moocode'=> true, 'moon'=> true, 'moonscript'=> true, 'mosel'=> true, 'mozhashpreproc'=> true, 'mozpercentpreproc'=> true, 'mq4'=> true, 'mq5'=> true, 'mql'=> true, 'mql4'=> true, 'mql5'=> true, 'ms'=> true, 'msc'=> true, 'mscgen'=> true, 'mupad'=> true, 'mxml'=> true, 'myghty'=> true, 'mysql'=> true, 'nasm'=> true, 'nawk'=> true, 'nb'=> true, 'ncl'=> true, 'nemerle'=> true, 'nesc'=> true, 'newlisp'=> true, 'newspeak'=> true, 'ng2'=> true, 'nginx'=> true, 'nim'=> true, 'nimrod'=> true, 'nit'=> true, 'nix'=> true, 'nixos'=> true, 'notmuch'=> true, 'nroff'=> true, 'nsh'=> true, 'nsi'=> true, 'nsis'=> true, 'numpy'=> true, 'nusmv'=> true, 'obj-c'=> true, 'obj-c++'=> true, 'obj-j'=> true, 'objc'=> true, 'objc++'=> true, 'objdump'=> true, 'objdump-nasm'=> true, 'objective-c'=> true, 'objective-c++'=> true, 'objective-j'=> true, 'objectivec'=> true, 'objectivec++'=> true, 'objectivej'=> true, 'objectpascal'=> true, 'objj'=> true, 'ocaml'=> true, 'octave'=> true, 'odin'=> true, 'ooc'=> true, 'opa'=> true, 'openbugs'=> true, 'openedge'=> true, 'pacmanconf'=> true, 'pan'=> true, 'parasail'=> true, 'pas'=> true, 'pascal'=> true, 'pawn'=> true, 'pcmk'=> true, 'peg'=> true, 'perl'=> true, 'perl6'=> true, 'php'=> true, 'php3'=> true, 'php4'=> true, 'php5'=> true, 'pig'=> true, 'pike'=> true, 'pkgconfig'=> true, 'pl'=> true, 'pl6'=> true, 'plpgsql'=> true, 'po'=> true, 'pointless'=> true, 'pony'=> true, 'posh'=> true, 'postgres'=> true, 'postgres-console'=> true, 'postgresql'=> true, 'postgresql-console'=> true, 'postscr'=> true, 'postscript'=> true, 'pot'=> true, 'pov'=> true, 'powershell'=> true, 'praat'=> true, 'progress'=> true, 'prolog'=> true, 'promql'=> true, 'properties'=> true, 'proto'=> true, 'protobuf'=> true, 'ps1'=> true, 'ps1con'=> true, 'psm1'=> true, 'psql'=> true, 'psysh'=> true, 'pug'=> true, 'puppet'=> true, 'py'=> true, 'py2'=> true, 'py2tb'=> true, 'py3'=> true, 'py3tb'=> true, 'pycon'=> true, 'pypy'=> true, 'pypylog'=> true, 'pyrex'=> true, 'pytb'=> true, 'python'=> true, 'python2'=> true, 'python3'=> true, 'pyx'=> true, 'qbasic'=> true, 'qbs'=> true, 'qml'=> true, 'qvt'=> true, 'qvto'=> true, 'r'=> true, 'racket'=> true, 'ragel'=> true, 'ragel-c'=> true, 'ragel-cpp'=> true, 'ragel-d'=> true, 'ragel-em'=> true, 'ragel-java'=> true, 'ragel-objc'=> true, 'ragel-rb'=> true, 'ragel-ruby'=> true, 'raku'=> true, 'raw'=> true, 'rb'=> true, 'rbcon'=> true, 'rconsole'=> true, 'rd'=> true, 'reason'=> true, 'reasonml'=> true, 'rebol'=> true, 'red'=> true, 'red/system'=> true, 'redcode'=> true, 'registry'=> true, 'resource'=> true, 'resourcebundle'=> true, 'rest'=> true, 'restructuredtext'=> true, 'rexx'=> true, 'rhtml'=> true, 'ride'=> true, 'rkt'=> true, 'rnc'=> true, 'rng-compact'=> true, 'roboconf-graph'=> true, 'roboconf-instances'=> true, 'robotframework'=> true, 'rout'=> true, 'rql'=> true, 'rs'=> true, 'rsl'=> true, 'rst'=> true, 'rts'=> true, 'ruby'=> true, 'rust'=> true, 's'=> true, 'sage'=> true, 'salt'=> true, 'sarl'=> true, 'sas'=> true, 'sass'=> true, 'sbatch'=> true, 'sc'=> true, 'scala'=> true, 'scaml'=> true, 'scd'=> true, 'scdoc'=> true, 'scheme'=> true, 'scilab'=> true, 'scm'=> true, 'scss'=> true, 'sgf'=> true, 'sh'=> true, 'shell'=> true, 'shell-session'=> true, 'shen'=> true, 'shex'=> true, 'shexc'=> true, 'sieve'=> true, 'silver'=> true, 'singularity'=> true, 'slash'=> true, 'slim'=> true, 'sls'=> true, 'slurm'=> true, 'smali'=> true, 'smalltalk'=> true, 'smarty'=> true, 'sml'=> true, 'snobol'=> true, 'snowball'=> true, 'solidity'=> true, 'sources.list'=> true, 'sourceslist'=> true, 'sp'=> true, 'sparql'=> true, 'spec'=> true, 'spitfire'=> true, 'splus'=> true, 'sql'=> true, 'sqlite3'=> true, 'squeak'=> true, 'squid'=> true, 'squid.conf'=> true, 'squidconf'=> true, 'ssp'=> true, 'st'=> true, 'stan'=> true, 'stata'=> true, 'supercollider'=> true, 'sv'=> true, 'swift'=> true, 'swig'=> true, 'systemverilog'=> true, 't-sql'=> true, 'tads3'=> true, 'tap'=> true, 'tasm'=> true, 'tcl'=> true, 'tcsh'=> true, 'tcshcon'=> true, 'tea'=> true, 'teraterm'=> true, 'teratermmacro'=> true, 'termcap'=> true, 'terminfo'=> true, 'terraform'=> true, 'tex'=> true, 'text'=> true, 'tf'=> true, 'thrift'=> true, 'tid'=> true, 'tnt'=> true, 'todotxt'=> true, 'toml'=> true, 'trac-wiki'=> true, 'trafficscript'=> true, 'treetop'=> true, 'ts'=> true, 'tsql'=> true, 'ttl'=> true, 'turtle'=> true, 'twig'=> true, 'typescript'=> true, 'typoscript'=> true, 'typoscriptcssdata'=> true, 'typoscripthtmldata'=> true, 'ucode'=> true, 'udiff'=> true, 'unicon'=> true, 'urbiscript'=> true, 'usd'=> true, 'usda'=> true, 'v'=> true, 'vala'=> true, 'vapi'=> true, 'vb.net'=> true, 'vbnet'=> true, 'vbscript'=> true, 'vcl'=> true, 'vclsnippet'=> true, 'vclsnippets'=> true, 'vctreestatus'=> true, 'velocity'=> true, 'verilog'=> true, 'vfp'=> true, 'vgl'=> true, 'vhdl'=> true, 'vim'=> true, 'wdiff'=> true, 'webidl'=> true, 'whiley'=> true, 'winbatch'=> true, 'winbugs'=> true, 'x10'=> true, 'xbase'=> true, 'xml'=> true, 'xml+cheetah'=> true, 'xml+django'=> true, 'xml+erb'=> true, 'xml+evoque'=> true, 'xml+genshi'=> true, 'xml+jinja'=> true, 'xml+kid'=> true, 'xml+lasso'=> true, 'xml+mako'=> true, 'xml+myghty'=> true, 'xml+php'=> true, 'xml+ruby'=> true, 'xml+smarty'=> true, 'xml+spitfire'=> true, 'xml+velocity'=> true, 'xorg.conf'=> true, 'xq'=> true, 'xql'=> true, 'xqm'=> true, 'xquery'=> true, 'xqy'=> true, 'xslt'=> true, 'xten'=> true, 'xtend'=> true, 'xul+mozpreproc'=> true, 'yaml'=> true, 'yaml+jinja'=> true, 'yang'=> true, 'zeek'=> true, 'zephir'=> true, 'zig'=> true, 'zsh'=> true,]
static getSoftwareTags( $all=false)
Loads defined core tags, checks for invalid types (if not array), and filters for supported and enabl...
A content handler knows how do deal with a specific type of content on a wiki page.
getParserOutputForIndexing(WikiPage $page, ParserCache $cache=null)
Produce page output suitable for indexing.
getSlotDiffRenderer(IContextSource $context, array $options=[])
Get an appropriate SlotDiffRenderer for this content model.
getModelID()
Returns the model id that identifies the content model this ContentHandler can handle.
makeRedirectContent(Title $destination, $text='')
Creates a new Content object that acts as a redirect to the given page, or null if redirects are not ...
__construct( $modelId, $formats)
Constructor, initializing the ContentHandler instance with its model ID and a list of supported forma...
static getAllContentFormats()
string[] $mSupportedFormats
getChangeType(Content $oldContent=null, Content $newContent=null, $flags=0)
Return type of change if one exists for the given edit.
checkModelID( $model_id)
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
importTransform( $blob, $format=null)
Apply import transformation (per default, returns $blob unchanged).
isParserCacheSupported()
Returns true for content models that support caching using the ParserCache mechanism.
static getForModelID( $modelId)
Returns the ContentHandler singleton for the given model ID.
supportsDirectApiEditing()
Whether or not this content model supports direct editing via ApiEditPage.
getAutoDeleteReason(Title $title, &$hasHistory)
Auto-generates a deletion reason.
getChangeTag(Content $oldContent=null, Content $newContent=null, $flags=0)
Return an applicable tag if one exists for the given edit or return null.
getDiffEngineClass()
Returns the name of the diff engine to use.
static getForTitle(Title $title)
Returns the appropriate ContentHandler singleton for the given title.
exportTransform( $blob, $format=null)
Applies transformations on export (returns the blob unchanged per default).
merge3(Content $oldContent, Content $myContent, Content $yourContent)
Attempts to merge differences between three versions.
getAutosummary(Content $oldContent=null, Content $newContent=null, $flags=0)
Return an applicable auto-summary if one exists for the given edit.
checkFormat( $format)
Convenient for checking whether a format provided as a parameter is actually supported.
addSearchField(&$fields, SearchEngine $engine, $name, $type)
Add new field definition to array.
getActionOverrides()
Returns overrides for action handlers.
createDifferenceEngine(IContextSource $context, $old=0, $new=0, $rcid=0, $refreshCache=false, $unhide=false)
Factory for creating an appropriate DifferenceEngine for this content model.
getSecondaryDataUpdates(Title $title, Content $content, $role, SlotRenderingProvider $slotOutput)
Returns a list of DeferrableUpdate objects for recording information about the given Content in some ...
static getContentModels()
getPageLanguage(Title $title, Content $content=null)
Get the language in which the content of the given page is written.
getDefaultFormat()
The format used for serialization/deserialization by default by this ContentHandler.
getSlotDiffRendererInternal(IContextSource $context)
Return the SlotDiffRenderer appropriate for this content handler.
static getDefaultModelFor(Title $title)
Returns the name of the default content model to be used for the page with the given title.
unserializeContent( $blob, $format=null)
Unserializes a Content object of the type supported by this ContentHandler.
static getLocalizedName( $name, Language $lang=null)
Returns the localized name for a given content model.
latestRevision(WikiPage $page)
supportsDirectEditing()
Return true if this content model supports direct editing, such as via EditPage.
getDeletionUpdates(Title $title, $role)
Returns a list of DeferrableUpdate objects for removing information about content in some secondary d...
isSupportedFormat( $format)
Returns true if $format is a serialization format supported by this ContentHandler,...
getSupportedFormats()
Returns a list of serialization formats supported by the serializeContent() and unserializeContent() ...
supportsSections()
Returns true if this content model supports sections.
static cleanupHandlersCache()
static getContentText(Content $content=null)
Convenience function for getting flat text from a Content object.
getDataForSearchIndex(WikiPage $page, ParserOutput $output, SearchEngine $engine)
Return fields to be indexed by search engine as representation of this document.
getSlotDiffRendererWithOptions(IContextSource $context, $options=[])
Return the SlotDiffRenderer appropriate for this content handler.
supportsCategories()
Returns true if this content model supports categories.
static getForContent(Content $content)
Returns the appropriate ContentHandler singleton for the given Content object.
supportsRedirects()
Returns true if this content model supports redirects.
canBeUsedOn(Title $title)
Determines whether the content type handled by this ContentHandler can be used for the main slot of t...
serializeContent(Content $content, $format=null)
Serializes a Content object of the type supported by this ContentHandler.
makeEmptyContent()
Creates an empty Content object of the type supported by this ContentHandler.
getFieldsForSearchIndex(SearchEngine $engine)
Get fields definition for search index.
getUndoContent( $current, $undo, $undoafter, $undoIsLatest=false)
Get the Content object that needs to be saved in order to undo all revisions between $undo and $undoa...
getPageViewLanguage(Title $title, Content $content=null)
Get the language in which the content of this page is written when viewed by user.
getLanguageConverter( $language)
Shorthand for getting a Language Converter for specific language.
B/C adapter for turning a DifferenceEngine into a SlotDiffRenderer.
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition Language.php:41
MediaWiki exception.
PSR-3 logger instance factory.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Page revision base class.
Value object representing a content slot associated with a page revision.
Extracts data from ParserOutput for indexing in the search engine.
Contain a class for special pages Stable to extend.
makeSearchFieldMapping( $name, $type)
Create a search field definition.
Content object implementation for representing flat text.
Renders a slot diff by doing a text diff on the native representation.
const ENGINE_PHP
Use the PHP diff implementation (DiffEngine).
const ENGINE_EXTERNAL
Use an external executable.
const ENGINE_WIKIDIFF2
Use the wikidiff2 PHP module.
const ENGINE_WIKIDIFF2_INLINE
Use the wikidiff2 PHP module.
Represents a title within MediaWiki.
Definition Title.php:42
Class representing a MediaWiki article and history.
Definition WikiPage.php:51
getContent( $audience=RevisionRecord::FOR_PUBLIC, User $user=null)
Get the content of the current revision.
Definition WikiPage.php:802
makeParserOptions( $context)
Get parser options suitable for rendering the primary article wikitext.
getTitle()
Get the title object of the article.
Definition WikiPage.php:318
loadPageData( $from='fromdb')
Load the object from a given source by title.
Definition WikiPage.php:465
getRevisionRecord()
Get the latest revision.
Definition WikiPage.php:781
const NS_MEDIAWIKI
Definition Defines.php:78
const EDIT_NEW
Definition Defines.php:142
Base interface for content objects.
Definition Content.php:35
Interface for objects which can provide a MediaWiki context on request.
The shared interface for all language converters.
A lazy provider of ParserOutput objects for a revision's individual slots.
$cache
Definition mcc.php:33
const DB_REPLICA
Definition defines.php:25
$content
Definition router.php:76
if(!isset( $args[0])) $lang