33use Wikimedia\Assert\Assert;
116 $this->mTitle = clone $this->mTitle;
128 $ns = $title->getNamespace();
131 throw new MWException(
"NS_MEDIA is a virtual namespace; use NS_FILE." );
132 } elseif ( $ns < 0 ) {
133 throw new MWException(
"Invalid or virtual namespace $ns given." );
137 if ( !Hooks::run(
'WikiPageFactory', [ $title, &$page ] ) ) {
165 public static function newFromID( $id, $from =
'fromdb' ) {
171 $from = self::convertSelectType( $from );
173 $pageQuery = self::getQueryInfo();
174 $row = $db->selectRow(
175 $pageQuery[
'tables'], $pageQuery[
'fields'], [
'page_id' => $id ], __METHOD__,
176 [], $pageQuery[
'joins']
181 return self::newFromRow( $row, $from );
195 public static function newFromRow( $row, $from =
'fromdb' ) {
196 $page = self::factory( Title::newFromRow( $row ) );
197 $page->loadFromRow( $row, $from );
210 return self::READ_NORMAL;
212 return self::READ_LATEST;
214 return self::READ_LOCKING;
225 return MediaWikiServices::getInstance()->getRevisionStore();
232 return MediaWikiServices::getInstance()->getRevisionRenderer();
239 return MediaWikiServices::getInstance()->getParserCache();
246 return MediaWikiServices::getInstance()->getDBLoadBalancer();
269 return ContentHandler::getForModelID( $this->getContentModel() );
277 return $this->mTitle;
285 $this->mDataLoaded =
false;
286 $this->mDataLoadedFrom = self::READ_NONE;
297 $this->mRedirectTarget =
null;
298 $this->mLastRevision =
null;
299 $this->mTouched =
'19700101000000';
300 $this->mLinksUpdated =
'19700101000000';
301 $this->mTimestamp =
'';
302 $this->mIsRedirect =
false;
303 $this->mLatest =
false;
316 $this->mPreparedEdit =
false;
340 'page_links_updated',
346 $fields[] =
'page_content_model';
350 $fields[] =
'page_lang';
369 'tables' => [
'page' ],
379 'page_links_updated',
387 $ret[
'fields'][] =
'page_content_model';
391 $ret[
'fields'][] =
'page_lang';
405 $pageQuery = self::getQueryInfo();
410 Hooks::run(
'ArticlePageDataBefore', [
411 &$wikiPage, &$pageQuery[
'fields'], &$pageQuery[
'tables'], &$pageQuery[
'joins']
414 $row =
$dbr->selectRow(
415 $pageQuery[
'tables'],
416 $pageQuery[
'fields'],
423 Hooks::run(
'ArticlePageDataAfter', [ &$wikiPage, &$row ] );
439 'page_namespace' => $title->getNamespace(),
440 'page_title' => $title->getDBkey() ],
$options );
468 $from = self::convertSelectType( $from );
469 if ( is_int( $from ) && $from <= $this->mDataLoadedFrom ) {
474 if ( is_int( $from ) ) {
475 list( $index, $opts ) = DBAccessObjectUtils::getDBOptions( $from );
477 $db = $loadBalancer->getConnection( $index );
482 && $loadBalancer->getServerCount() > 1
483 && $loadBalancer->hasOrMadeRecentMasterChanges()
485 $from = self::READ_LATEST;
486 list( $index, $opts ) = DBAccessObjectUtils::getDBOptions( $from );
487 $db = $loadBalancer->getConnection( $index );
493 $from = self::READ_NORMAL;
513 $from = self::convertSelectType( $from );
515 if ( !is_int( $from ) ) {
517 $from = self::READ_NORMAL;
520 if ( is_int( $from ) && $from <= $this->mDataLoadedFrom ) {
539 $lc = MediaWikiServices::getInstance()->getLinkCache();
540 $lc->clearLink( $this->mTitle );
543 $lc->addGoodLinkObjFromRow( $this->mTitle, $data );
545 $this->mTitle->loadFromRow( $data );
548 $this->mTitle->loadRestrictions( $data->page_restrictions );
550 $this->mId = intval( $data->page_id );
551 $this->mTouched =
wfTimestamp( TS_MW, $data->page_touched );
553 $this->mIsRedirect = intval( $data->page_is_redirect );
554 $this->mLatest = intval( $data->page_latest );
557 if ( $this->mLastRevision && $this->mLastRevision->getId() != $this->mLatest ) {
558 $this->mLastRevision =
null;
559 $this->mTimestamp =
'';
562 $lc->addBadLinkObj( $this->mTitle );
564 $this->mTitle->loadFromRow(
false );
571 $this->mDataLoaded =
true;
572 $this->mDataLoadedFrom = self::convertSelectType( $from );
579 if ( !$this->mDataLoaded ) {
589 if ( !$this->mDataLoaded ) {
592 return $this->mId > 0;
604 return $this->mTitle->isKnown();
613 if ( !$this->mDataLoaded ) {
617 return (
bool)$this->mIsRedirect;
632 $cache = ObjectCache::getMainWANInstance();
634 return $cache->getWithSetCallback(
635 $cache->makeKey(
'page-content-model', $this->getLatest() ),
641 return $rev->getContentModel();
643 $title = $this->mTitle->getPrefixedDBkey();
644 wfWarn(
"Page $title exists but has no (visible) revisions!" );
645 return $this->mTitle->getContentModel();
652 return $this->mTitle->getContentModel();
660 if ( !$this->mDataLoaded ) {
663 return ( $this->mId && !$this->mIsRedirect );
671 if ( !$this->mDataLoaded ) {
674 return $this->mTouched;
682 if ( !$this->mDataLoaded ) {
685 return $this->mLinksUpdated;
693 if ( !$this->mDataLoaded ) {
696 return (
int)$this->mLatest;
705 $rev = $this->mTitle->getFirstRevision();
707 $rev = $this->mTitle->getFirstRevision( Title::GAID_FOR_UPDATE );
717 if ( $this->mLastRevision !==
null ) {
726 if ( $this->mDataLoadedFrom == self::READ_LOCKING ) {
736 } elseif ( $this->mDataLoadedFrom == self::READ_LATEST ) {
740 $flags = Revision::READ_LATEST;
757 $this->mLastRevision = $revision;
767 if ( $this->mLastRevision ) {
768 return $this->mLastRevision;
779 if ( $this->mLastRevision ) {
780 return $this->mLastRevision->getRevisionRecord();
800 if ( $this->mLastRevision ) {
801 return $this->mLastRevision->getContent( $audience, $user );
811 if ( !$this->mTimestamp ) {
838 if ( $this->mLastRevision ) {
839 return $this->mLastRevision->getUser( $audience, $user );
858 $userName = $revision->getUserText( $audience, $user );
876 if ( $this->mLastRevision ) {
877 return $this->mLastRevision->getUserText( $audience, $user );
894 if ( $this->mLastRevision ) {
895 return $this->mLastRevision->getComment( $audience, $user );
908 if ( $this->mLastRevision ) {
909 return $this->mLastRevision->isMinor();
928 if ( !$this->mTitle->isContentPage() ) {
953 $hasLinks = (bool)count( $editInfo->output->getLinks() );
957 [
'pl_from' => $this->
getId() ], __METHOD__ );
961 return $content->isCountable( $hasLinks );
972 if ( !$this->mTitle->isRedirect() ) {
976 if ( $this->mRedirectTarget !==
null ) {
977 return $this->mRedirectTarget;
982 $row =
$dbr->selectRow(
'redirect',
983 [
'rd_namespace',
'rd_title',
'rd_fragment',
'rd_interwiki' ],
984 [
'rd_from' => $this->
getId() ],
989 if ( $row && !is_null( $row->rd_fragment ) && !is_null( $row->rd_interwiki ) ) {
993 if ( $row->rd_namespace ==
NS_MEDIA ) {
996 $namespace = $row->rd_namespace;
998 $this->mRedirectTarget = Title::makeTitle(
999 $namespace, $row->rd_title,
1000 $row->rd_fragment, $row->rd_interwiki
1002 return $this->mRedirectTarget;
1007 return $this->mRedirectTarget;
1027 DeferredUpdates::addCallableUpdate(
1028 function () use (
$retval, $latest ) {
1031 DeferredUpdates::POSTSEND,
1045 $dbw->startAtomic( __METHOD__ );
1051 'rd_from' => $this->
getId(),
1052 'rd_namespace' => $rt->getNamespace(),
1053 'rd_title' => $rt->getDBkey(),
1054 'rd_fragment' => $rt->getFragment(),
1055 'rd_interwiki' => $rt->getInterwiki(),
1059 'rd_namespace' => $rt->getNamespace(),
1060 'rd_title' => $rt->getDBkey(),
1061 'rd_fragment' => $rt->getFragment(),
1062 'rd_interwiki' => $rt->getInterwiki(),
1068 $dbw->endAtomic( __METHOD__ );
1092 if ( $rt->isExternal() ) {
1093 if ( $rt->isLocal() ) {
1097 $source = $this->mTitle->getFullURL(
'redirect=no' );
1098 return $rt->getFullURL( [
'rdfrom' =>
$source ] );
1106 if ( $rt->isSpecialPage() ) {
1110 if ( $rt->isValidRedirectTarget() ) {
1111 return $rt->getFullURL();
1130 $actorMigration = ActorMigration::newMigration();
1131 $actorQuery = $actorMigration->getJoin(
'rev_user' );
1133 $tables = array_merge( [
'revision' ], $actorQuery[
'tables'], [
'user' ] );
1136 'user_id' => $actorQuery[
'fields'][
'rev_user'],
1137 'user_name' => $actorQuery[
'fields'][
'rev_user_text'],
1138 'actor_id' => $actorQuery[
'fields'][
'rev_actor'],
1139 'user_real_name' =>
'MIN(user_real_name)',
1140 'timestamp' =>
'MAX(rev_timestamp)',
1143 $conds = [
'rev_page' => $this->
getId() ];
1150 $conds[] =
'NOT(' . $actorMigration->getWhere(
$dbr,
'rev_user', $user )[
'conds'] .
')';
1153 $conds[] =
"{$dbr->bitAnd( 'rev_deleted', Revision::DELETED_USER )} = 0";
1156 'user' => [
'LEFT JOIN', $actorQuery[
'fields'][
'rev_user'] .
' = user_id' ],
1157 ] + $actorQuery[
'joins'];
1160 'GROUP BY' => [ $fields[
'user_id'], $fields[
'user_name'] ],
1161 'ORDER BY' =>
'timestamp DESC',
1178 && ( $oldId ===
null || $oldId === 0 || $oldId === $this->
getLatest() )
1198 ParserOptions $parserOptions, $oldid =
null, $forceParse =
false
1203 if ( $useParserCache && !$parserOptions->
isSafeToCache() ) {
1204 throw new InvalidArgumentException(
1205 'The supplied ParserOptions are not safe to cache. Fix the options or set $forceParse = true.'
1210 ': using parser cache: ' . ( $useParserCache ?
'yes' :
'no' ) .
"\n" );
1215 if ( $useParserCache ) {
1217 ->get( $this, $parserOptions );
1218 if ( $parserOutput !==
false ) {
1219 return $parserOutput;
1223 if ( $oldid ===
null || $oldid === 0 ) {
1230 return $pool->getParserOutput();
1245 DeferredUpdates::addCallableUpdate(
1246 function () use ( $user, $oldid ) {
1247 Hooks::run(
'PageViewUpdates', [ $this, $user ] );
1249 $user->clearNotification( $this->mTitle, $oldid );
1251 DeferredUpdates::PRESEND
1265 if ( !Hooks::run(
'ArticlePurge', [ &$wikiPage ] ) ) {
1269 $this->mTitle->invalidateCache();
1274 DeferredUpdates::addUpdate(
1276 DeferredUpdates::PRESEND
1279 if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
1280 $messageCache = MessageCache::singleton();
1281 $messageCache->updateMessageOverride( $this->mTitle, $this->
getContent() );
1304 $pageIdForInsert = $pageId ? [
'page_id' => $pageId ] : [];
1308 'page_namespace' => $this->mTitle->getNamespace(),
1309 'page_title' => $this->mTitle->getDBkey(),
1310 'page_restrictions' =>
'',
1311 'page_is_redirect' => 0,
1314 'page_touched' => $dbw->timestamp(),
1317 ] + $pageIdForInsert,
1322 if ( $dbw->affectedRows() > 0 ) {
1323 $newid = $pageId ? (int)$pageId : $dbw->insertId();
1324 $this->mId = $newid;
1325 $this->mTitle->resetArticleID( $newid );
1349 $lastRevIsRedirect =
null
1358 if ( (
int)$revision->getId() === 0 ) {
1359 throw new InvalidArgumentException(
1360 __METHOD__ .
': Revision has ID ' . var_export( $revision->getId(), 1 )
1364 $content = $revision->getContent();
1368 $conditions = [
'page_id' => $this->
getId() ];
1370 if ( !is_null( $lastRevision ) ) {
1372 $conditions[
'page_latest'] = $lastRevision;
1375 $revId = $revision->getId();
1376 Assert::parameter( $revId > 0,
'$revision->getId()',
'must be > 0' );
1379 'page_latest' => $revId,
1380 'page_touched' => $dbw->timestamp( $revision->getTimestamp() ),
1381 'page_is_new' => ( $lastRevision === 0 ) ? 1 : 0,
1382 'page_is_redirect' => $rt !==
null ? 1 : 0,
1387 $row[
'page_content_model'] = $revision->getContentModel();
1390 $dbw->update(
'page',
1395 $result = $dbw->affectedRows() > 0;
1399 $this->mLatest = $revision->getId();
1400 $this->mIsRedirect = (bool)$rt;
1402 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1403 $linkCache->addGoodLinkObj(
1409 $revision->getContentModel()
1431 $isRedirect = !is_null( $redirectTitle );
1433 if ( !$isRedirect && $lastRevIsRedirect ===
false ) {
1437 if ( $isRedirect ) {
1441 $where = [
'rd_from' => $this->
getId() ];
1442 $dbw->delete(
'redirect', $where, __METHOD__ );
1449 return ( $dbw->affectedRows() != 0 );
1463 $row = $dbw->selectRow(
1464 [
'revision',
'page' ],
1465 [
'rev_id',
'rev_timestamp',
'page_is_redirect' ],
1467 'page_id' => $this->
getId(),
1468 'page_latest=rev_id' ],
1472 if (
wfTimestamp( TS_MW, $row->rev_timestamp ) >= $revision->getTimestamp() ) {
1475 $prev = $row->rev_id;
1476 $lastRevIsRedirect = (bool)$row->page_is_redirect;
1480 $lastRevIsRedirect =
null;
1501 $aSlots = $a->getRevisionRecord()->getSlots();
1502 $bSlots = $b->getRevisionRecord()->getSlots();
1503 $changedRoles = $aSlots->getRolesWithDifferentContent( $bSlots );
1505 return ( $changedRoles !== [ SlotRecord::MAIN ] && $changedRoles !== [] );
1522 if ( self::hasDifferencesOutsideMainSlot( $undo, $undoafter ) ) {
1560 $sectionId,
Content $sectionContent, $sectionTitle =
'', $edittime =
null
1563 if ( $edittime && $sectionId !==
'new' ) {
1571 && $lb->getServerCount() > 1
1572 && $lb->hasOrMadeRecentMasterChanges()
1578 $baseRevId =
$rev->getId();
1582 return $this->
replaceSectionAtRev( $sectionId, $sectionContent, $sectionTitle, $baseRevId );
1599 $sectionTitle =
'', $baseRevId =
null
1601 if ( strval( $sectionId ) ===
'' ) {
1603 $newContent = $sectionContent;
1606 throw new MWException(
"sections not supported for content model " .
1611 if ( is_null( $baseRevId ) || $sectionId ===
'new' ) {
1616 wfDebug( __METHOD__ .
" asked for bogus section (page: " .
1617 $this->
getId() .
"; section: $sectionId)\n" );
1621 $oldContent =
$rev->getContent();
1624 if ( !$oldContent ) {
1625 wfDebug( __METHOD__ .
": no page text\n" );
1629 $newContent = $oldContent->replaceSection( $sectionId, $sectionContent, $sectionTitle );
1667 JobQueueGroup::singleton(),
1668 MessageCache::singleton(),
1669 MediaWikiServices::getInstance()->getContentLanguage(),
1670 MediaWikiServices::getInstance()->getDBLoadBalancerFactory()
1707 User $forUser =
null,
1712 if ( !$forRevision && !$forUpdate ) {
1715 $this->derivedDataUpdater =
null;
1718 if ( $this->derivedDataUpdater && !$this->derivedDataUpdater->isContentPrepared() ) {
1722 $this->derivedDataUpdater =
null;
1729 if ( $this->derivedDataUpdater
1730 && !$this->derivedDataUpdater->isReusableFor(
1734 $forEdit ? $this->getLatest() : null
1737 $this->derivedDataUpdater =
null;
1740 if ( !$this->derivedDataUpdater ) {
1744 return $this->derivedDataUpdater;
1777 return $pageUpdater;
1844 User $user =
null, $serialFormat =
null, $tags = [], $undidRevId = 0
1849 $summary = CommentStoreComment::newUnsavedComment( trim( $summary ) );
1859 if ( ( $flags &
EDIT_MINOR ) && !$user->isAllowed(
'minoredit' ) ) {
1860 $flags = ( $flags & ~EDIT_MINOR );
1864 $slotsUpdate->modifyContent( SlotRecord::MAIN,
$content );
1871 $updater->setOriginalRevisionId( $originalRevId );
1872 $updater->setUndidRevisionId( $undidRevId );
1879 if ( $needsPatrol && $this->
getTitle()->userCan(
'autopatrol', $user ) ) {
1880 $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
1897 $this->mLatest = $revRec->getId();
1920 if ( $this->
getTitle()->isConversionTable() ) {
1923 $options->disableContentConversion();
1953 $serialFormat =
null,
1962 if ( !is_object( $revision ) ) {
1966 if ( $revid !==
null ) {
1967 wfDeprecated( __METHOD__ .
' with $revision = revision ID',
'1.25' );
1969 $revision = $store->getRevisionById( $revid, Revision::READ_LATEST );
1973 } elseif ( $revision instanceof
Revision ) {
1974 $revision = $revision->getRevisionRecord();
1977 $slots = RevisionSlotsUpdate::newFromContent( [ SlotRecord::MAIN =>
$content ] );
1980 if ( !
$updater->isUpdatePrepared() ) {
1981 $updater->prepareContent( $user, $slots, $useCache );
1987 'causeAction' =>
'prepare-edit',
1988 'causeAgent' => $user->getName(),
1994 return $updater->getPreparedEdit();
2026 'causeAction' =>
'edit-page',
2027 'causeAgent' => $user->getName(),
2054 if ( !$revision || !$revision->getId() ) {
2055 LoggerFactory::getInstance(
'wikipage' )->info(
2056 __METHOD__ .
'called with ' . ( $revision ?
'unsaved' :
'no' ) .
' revision'
2096 if ( !$revision || !$revision->getId() ) {
2097 LoggerFactory::getInstance(
'wikipage' )->info(
2098 __METHOD__ .
'called with ' . ( $revision ?
'unsaved' :
'no' ) .
' revision'
2124 &$cascade, $reason,
User $user, $tags =
null
2133 $restrictionTypes = $this->mTitle->getRestrictionTypes();
2134 $id = $this->
getId();
2141 Title::purgeExpiredRestrictions();
2145 $isProtected =
false;
2151 foreach ( $restrictionTypes as $action ) {
2152 if ( !isset( $expiry[$action] ) || $expiry[$action] === $dbw->getInfinity() ) {
2153 $expiry[$action] =
'infinity';
2155 if ( !isset( $limit[$action] ) ) {
2156 $limit[$action] =
'';
2157 } elseif ( $limit[$action] !=
'' ) {
2162 $current = implode(
'', $this->mTitle->getRestrictions( $action ) );
2163 if ( $current !=
'' ) {
2164 $isProtected =
true;
2167 if ( $limit[$action] != $current ) {
2169 } elseif ( $limit[$action] !=
'' ) {
2173 if ( $this->mTitle->getRestrictionExpiry( $action ) != $expiry[$action] ) {
2179 if ( !$changed && $protect && $this->mTitle->areRestrictionsCascading() != $cascade ) {
2185 return Status::newGood();
2189 $revCommentMsg =
'unprotectedarticle-comment';
2190 $logAction =
'unprotect';
2191 } elseif ( $isProtected ) {
2192 $revCommentMsg =
'modifiedarticleprotection-comment';
2193 $logAction =
'modify';
2195 $revCommentMsg =
'protectedarticle-comment';
2196 $logAction =
'protect';
2199 $logRelationsValues = [];
2200 $logRelationsField =
null;
2201 $logParamsDetails = [];
2204 $nullRevision =
null;
2210 if ( !Hooks::run(
'ArticleProtect', [ &$wikiPage, &$user, $limit, $reason ] ) ) {
2211 return Status::newGood();
2215 $editrestriction = isset( $limit[
'edit'] )
2216 ? [ $limit[
'edit'] ]
2217 : $this->mTitle->getRestrictions(
'edit' );
2218 foreach ( array_keys( $editrestriction,
'sysop' ) as $key ) {
2219 $editrestriction[$key] =
'editprotected';
2221 foreach ( array_keys( $editrestriction,
'autoconfirmed' ) as $key ) {
2222 $editrestriction[$key] =
'editsemiprotected';
2226 foreach ( array_keys( $cascadingRestrictionLevels,
'sysop' ) as $key ) {
2227 $cascadingRestrictionLevels[$key] =
'editprotected';
2229 foreach ( array_keys( $cascadingRestrictionLevels,
'autoconfirmed' ) as $key ) {
2230 $cascadingRestrictionLevels[$key] =
'editsemiprotected';
2234 if ( !array_intersect( $editrestriction, $cascadingRestrictionLevels ) ) {
2249 if ( $nullRevision ===
null ) {
2250 return Status::newFatal(
'no-null-revision', $this->mTitle->getPrefixedText() );
2253 $logRelationsField =
'pr_id';
2256 foreach ( $limit as $action => $restrictions ) {
2258 'page_restrictions',
2261 'pr_type' => $action
2265 if ( $restrictions !=
'' ) {
2266 $cascadeValue = ( $cascade && $action ==
'edit' ) ? 1 : 0;
2268 'page_restrictions',
2271 'pr_type' => $action,
2272 'pr_level' => $restrictions,
2273 'pr_cascade' => $cascadeValue,
2274 'pr_expiry' => $dbw->encodeExpiry( $expiry[$action] )
2278 $logRelationsValues[] = $dbw->insertId();
2279 $logParamsDetails[] = [
2281 'level' => $restrictions,
2282 'expiry' => $expiry[$action],
2283 'cascade' => (bool)$cascadeValue,
2291 [
'page_restrictions' =>
'' ],
2292 [
'page_id' => $id ],
2299 Hooks::run(
'NewRevisionFromEditComplete',
2300 [ $this, $nullRevision, $latest, $user ] );
2301 Hooks::run(
'ArticleProtectComplete', [ &$wikiPage, &$user, $limit, $reason ] );
2306 if ( $limit[
'create'] !=
'' ) {
2307 $commentFields = CommentStore::getStore()->insert( $dbw,
'pt_reason', $reason );
2308 $dbw->replace(
'protected_titles',
2309 [ [
'pt_namespace',
'pt_title' ] ],
2311 'pt_namespace' => $this->mTitle->getNamespace(),
2312 'pt_title' => $this->mTitle->getDBkey(),
2313 'pt_create_perm' => $limit[
'create'],
2314 'pt_timestamp' => $dbw->timestamp(),
2315 'pt_expiry' => $dbw->encodeExpiry( $expiry[
'create'] ),
2316 'pt_user' => $user->getId(),
2317 ] + $commentFields, __METHOD__
2319 $logParamsDetails[] = [
2321 'level' => $limit[
'create'],
2322 'expiry' => $expiry[
'create'],
2325 $dbw->delete(
'protected_titles',
2327 'pt_namespace' => $this->mTitle->getNamespace(),
2328 'pt_title' => $this->mTitle->getDBkey()
2334 $this->mTitle->flushRestrictions();
2337 if ( $logAction ==
'unprotect' ) {
2342 '4::description' => $protectDescriptionLog,
2343 '5:bool:cascade' => $cascade,
2344 'details' => $logParamsDetails,
2350 $logEntry->setTarget( $this->mTitle );
2351 $logEntry->setComment( $reason );
2352 $logEntry->setPerformer( $user );
2353 $logEntry->setParameters(
$params );
2354 if ( !is_null( $nullRevision ) ) {
2355 $logEntry->setAssociatedRevId( $nullRevision->getId() );
2357 $logEntry->setTags( $tags );
2358 if ( $logRelationsField !==
null && count( $logRelationsValues ) ) {
2359 $logEntry->setRelations( [ $logRelationsField => $logRelationsValues ] );
2361 $logId = $logEntry->insert();
2362 $logEntry->publish( $logId );
2364 return Status::newGood( $logId );
2379 array $expiry, $cascade, $reason, $user =
null
2386 $this->mTitle->getPrefixedText(),
2387 $user ? $user->getName() :
''
2388 )->inContentLanguage()->text();
2390 $editComment .=
wfMessage(
'colon-separator' )->inContentLanguage()->text() . $reason;
2393 if ( $protectDescription ) {
2394 $editComment .=
wfMessage(
'word-separator' )->inContentLanguage()->text();
2395 $editComment .=
wfMessage(
'parentheses' )->params( $protectDescription )
2396 ->inContentLanguage()->text();
2399 $editComment .=
wfMessage(
'word-separator' )->inContentLanguage()->text();
2400 $editComment .=
wfMessage(
'brackets' )->params(
2401 wfMessage(
'protect-summary-cascade' )->inContentLanguage()->
text()
2402 )->inContentLanguage()->text();
2407 $nullRev->insertOn( $dbw );
2410 $oldLatest = $nullRev->getParentId();
2422 if ( $expiry !=
'infinity' ) {
2423 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
2426 $contLang->timeanddate( $expiry,
false,
false ),
2427 $contLang->date( $expiry,
false,
false ),
2428 $contLang->time( $expiry,
false,
false )
2429 )->inContentLanguage()->text();
2431 return wfMessage(
'protect-expiry-indefinite' )
2432 ->inContentLanguage()->text();
2444 $protectDescription =
'';
2446 foreach ( array_filter( $limit ) as $action => $restrictions ) {
2447 # $action is one of $wgRestrictionTypes = [ 'create', 'edit', 'move', 'upload' ].
2448 # All possible message keys are listed here for easier grepping:
2449 # * restriction-create
2450 # * restriction-edit
2451 # * restriction-move
2452 # * restriction-upload
2453 $actionText =
wfMessage(
'restriction-' . $action )->inContentLanguage()->text();
2454 # $restrictions is one of $wgRestrictionLevels = [ '', 'autoconfirmed', 'sysop' ],
2455 # with '' filtered out. All possible message keys are listed below:
2456 # * protect-level-autoconfirmed
2457 # * protect-level-sysop
2458 $restrictionsText =
wfMessage(
'protect-level-' . $restrictions )
2459 ->inContentLanguage()->text();
2463 if ( $protectDescription !==
'' ) {
2464 $protectDescription .=
wfMessage(
'word-separator' )->inContentLanguage()->text();
2466 $protectDescription .=
wfMessage(
'protect-summary-desc' )
2467 ->params( $actionText, $restrictionsText, $expiryText )
2468 ->inContentLanguage()->text();
2471 return $protectDescription;
2486 $protectDescriptionLog =
'';
2488 $dirMark = MediaWikiServices::getInstance()->getContentLanguage()->getDirMark();
2489 foreach ( array_filter( $limit ) as $action => $restrictions ) {
2491 $protectDescriptionLog .=
2493 "[$action=$restrictions] ($expiryText)";
2496 return trim( $protectDescriptionLog );
2509 if ( !is_array( $limit ) ) {
2510 throw new MWException( __METHOD__ .
' given non-array restriction set' );
2516 foreach ( array_filter( $limit ) as $action => $restrictions ) {
2517 $bits[] =
"$action=$restrictions";
2520 return implode(
':', $bits );
2540 $revCount += $safetyMargin;
2565 $reason, $suppress =
false, $u1 =
null, $u2 =
null, &$error =
'',
User $user =
null,
2569 [],
'delete', $immediate );
2598 $reason, $suppress =
false, $u1 =
null, $u2 =
null, &$error =
'',
User $deleter =
null,
2599 $tags = [], $logsubtype =
'delete', $immediate =
false
2610 $deleter = is_null( $deleter ) ? $wgUser : $deleter;
2611 if ( !Hooks::run(
'ArticleDelete',
2612 [ &$wikiPage, &$deleter, &$reason, &$error, &
$status, $suppress ]
2616 $status->fatal(
'delete-hook-aborted' );
2622 $logsubtype, $immediate );
2634 $reason, $suppress,
User $deleter, $tags,
2635 $logsubtype, $immediate =
false, $webRequestId =
null
2642 $dbw->startAtomic( __METHOD__ );
2645 $id = $this->
getId();
2651 if ( $id == 0 || $this->
getLatest() != $lockedLatest ) {
2652 $dbw->endAtomic( __METHOD__ );
2654 $status->error(
'cannotdelete',
2668 }
catch ( Exception $ex ) {
2669 wfLogWarning( __METHOD__ .
': failed to load content during deletion! '
2670 . $ex->getMessage() );
2677 $explictTrxLogged =
false;
2680 if ( $done || !$immediate ) {
2683 $dbw->endAtomic( __METHOD__ );
2684 if ( $dbw->explicitTrxActive() ) {
2686 if ( !$explictTrxLogged ) {
2687 $explictTrxLogged =
true;
2688 LoggerFactory::getInstance(
'wfDebug' )->debug(
2689 'explicit transaction active in ' . __METHOD__ .
' while deleting {title}', [
2690 'title' => $this->
getTitle()->getText(),
2695 if ( $dbw->trxLevel() ) {
2698 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
2699 $lbFactory->waitForReplication();
2700 $dbw->startAtomic( __METHOD__ );
2705 $dbw->endAtomic( __METHOD__ );
2708 'wikiPageId' => $id,
2709 'requestId' => $webRequestId ?? WebRequest::getRequestId(),
2710 'reason' => $reason,
2711 'suppress' => $suppress,
2712 'userId' => $deleter->getId(),
2713 'tags' => json_encode( $tags ),
2714 'logsubtype' => $logsubtype,
2718 JobQueueGroup::singleton()->push(
$job );
2720 $status->warning(
'delete-scheduled',
2730 $archivedRevisionCount = $dbw->selectField(
2731 'archive',
'COUNT(*)',
2733 'ar_namespace' => $this->
getTitle()->getNamespace(),
2734 'ar_title' => $this->
getTitle()->getDBkey(),
2741 $logTitle = clone $this->mTitle;
2742 $wikiPageBeforeDelete = clone $this;
2745 $dbw->delete(
'page', [
'page_id' => $id ], __METHOD__ );
2748 $logtype = $suppress ?
'suppress' :
'delete';
2751 $logEntry->setPerformer( $deleter );
2752 $logEntry->setTarget( $logTitle );
2753 $logEntry->setComment( $reason );
2754 $logEntry->setTags( $tags );
2755 $logid = $logEntry->insert();
2757 $dbw->onTransactionPreCommitOrIdle(
2758 function () use ( $logEntry, $logid ) {
2760 $logEntry->publish( $logid );
2765 $dbw->endAtomic( __METHOD__ );
2769 Hooks::run(
'ArticleDeleteComplete', [
2770 &$wikiPageBeforeDelete,
2776 $archivedRevisionCount
2781 $cache = MediaWikiServices::getInstance()->getMainObjectStash();
2782 $key =
$cache->makeKey(
'page-recent-delete', md5( $logTitle->getPrefixedText() ) );
2783 $cache->set( $key, 1, $cache::TTL_DAY );
2804 $namespace = $this->
getTitle()->getNamespace();
2805 $dbKey = $this->
getTitle()->getDBkey();
2807 $commentStore = CommentStore::getStore();
2808 $actorMigration = ActorMigration::newMigration();
2830 $dbw->lockForUpdate(
2833 [
'revision',
'revision_comment_temp',
'revision_actor_temp' ]
2835 [
'rev_page' => $id ],
2848 $revQuery[
'fields'][] =
'rev_content_model';
2849 $revQuery[
'fields'][] =
'rev_content_format';
2855 $res = $dbw->select(
2858 [
'rev_page' => $id ],
2872 foreach (
$res as $row ) {
2878 $comment = $commentStore->getComment(
'rev_comment', $row );
2881 'ar_namespace' => $namespace,
2882 'ar_title' => $dbKey,
2883 'ar_timestamp' => $row->rev_timestamp,
2884 'ar_minor_edit' => $row->rev_minor_edit,
2885 'ar_rev_id' => $row->rev_id,
2886 'ar_parent_id' => $row->rev_parent_id,
2895 'ar_len' => $row->rev_len,
2896 'ar_page_id' => $id,
2897 'ar_deleted' => $suppress ? $bitfield : $row->rev_deleted,
2898 'ar_sha1' => $row->rev_sha1,
2899 ] + $commentStore->insert( $dbw,
'ar_comment', $comment )
2900 + $actorMigration->getInsertValues( $dbw,
'ar_user', $user );
2903 $rowInsert[
'ar_text_id'] = $row->rev_text_id;
2906 $rowInsert[
'ar_content_model'] = $row->rev_content_model;
2907 $rowInsert[
'ar_content_format'] = $row->rev_content_format;
2911 $rowsInsert[] = $rowInsert;
2912 $revids[] = $row->rev_id;
2916 if ( (
int)$row->rev_user === 0 && IP::isValid( $row->rev_user_text ) ) {
2917 $ipRevIds[] = $row->rev_id;
2922 if ( count( $revids ) > 0 ) {
2924 $dbw->insert(
'archive', $rowsInsert, __METHOD__ );
2926 $dbw->delete(
'revision', [
'rev_id' => $revids ], __METHOD__ );
2928 $dbw->delete(
'revision_comment_temp', [
'revcomment_rev' => $revids ], __METHOD__ );
2931 $dbw->delete(
'revision_actor_temp', [
'revactor_rev' => $revids ], __METHOD__ );
2935 if ( count( $ipRevIds ) > 0 ) {
2936 $dbw->delete(
'ip_changes', [
'ipc_rev_id' => $ipRevIds ], __METHOD__ );
2954 'page_id' => $this->
getId(),
2957 'page_namespace' => $this->
getTitle()->getNamespace(),
2958 'page_title' => $this->
getTitle()->getDBkey()
2980 if ( $id !== $this->
getId() ) {
2981 throw new InvalidArgumentException(
'Mismatching page ID' );
2986 }
catch ( Exception $ex ) {
2993 DeferredUpdates::addUpdate( SiteStatsUpdate::factory(
2994 [
'edits' => 1,
'articles' => -$countable,
'pages' => -1 ]
2999 $revision ? $revision->getRevisionRecord() :
$content
3001 foreach ( $updates as $update ) {
3002 DeferredUpdates::addUpdate( $update );
3005 $causeAgent = $user ? $user->getName() :
'unknown';
3007 LinksUpdate::queueRecursiveJobsForTable(
3008 $this->mTitle,
'templatelinks',
'delete-page', $causeAgent );
3010 if ( $this->mTitle->getNamespace() ==
NS_FILE ) {
3011 LinksUpdate::queueRecursiveJobsForTable(
3012 $this->mTitle,
'imagelinks',
'delete-page', $causeAgent );
3016 self::onArticleDelete( $this->mTitle );
3017 ResourceLoaderWikiModule::invalidateModuleCache(
3018 $this->mTitle, $revision,
null,
wfWikiID()
3025 DeferredUpdates::addUpdate(
new SearchUpdate( $id, $this->mTitle ) );
3058 $fromP, $summary, $token, $bot, &$resultDetails,
User $user, $tags =
null
3060 $resultDetails =
null;
3063 $editErrors = $this->mTitle->getUserPermissionsErrors(
'edit', $user );
3064 $rollbackErrors = $this->mTitle->getUserPermissionsErrors(
'rollback', $user );
3065 $errors = array_merge( $editErrors,
wfArrayDiff2( $rollbackErrors, $editErrors ) );
3067 if ( !$user->matchEditToken( $token,
'rollback' ) ) {
3068 $errors[] = [
'sessionfailure' ];
3071 if ( $user->pingLimiter(
'rollback' ) || $user->pingLimiter() ) {
3072 $errors[] = [
'actionthrottledtext' ];
3076 if ( !empty( $errors ) ) {
3080 return $this->
commitRollback( $fromP, $summary, $bot, $resultDetails, $user, $tags );
3104 &$resultDetails,
User $guser, $tags =
null
3111 return [ [
'readonlytext' ] ];
3117 $current =
$updater->grabParentRevision();
3119 if ( is_null( $current ) ) {
3121 return [ [
'notanarticle' ] ];
3124 $currentEditorForPublic = $current->getUser( RevisionRecord::FOR_PUBLIC );
3125 $legacyCurrent =
new Revision( $current );
3126 $from = str_replace(
'_',
' ', $fromP );
3130 if ( $from !== ( $currentEditorForPublic ? $currentEditorForPublic->getName() :
'' ) ) {
3131 $resultDetails = [
'current' => $legacyCurrent ];
3132 return [ [
'alreadyrolled',
3133 htmlspecialchars( $this->mTitle->getPrefixedText() ),
3134 htmlspecialchars( $fromP ),
3135 htmlspecialchars( $currentEditorForPublic ? $currentEditorForPublic->getName() :
'' )
3141 $actorWhere = ActorMigration::newMigration()->getWhere(
3144 $current->getUser( RevisionRecord::RAW )
3147 $s = $dbw->selectRow(
3148 [
'revision' ] + $actorWhere[
'tables'],
3149 [
'rev_id',
'rev_timestamp',
'rev_deleted' ],
3151 'rev_page' => $current->getPageId(),
3152 'NOT(' . $actorWhere[
'conds'] .
')',
3156 'USE INDEX' => [
'revision' =>
'page_timestamp' ],
3157 'ORDER BY' =>
'rev_timestamp DESC'
3159 $actorWhere[
'joins']
3161 if (
$s ===
false ) {
3163 return [ [
'cantrollback' ] ];
3164 } elseif (
$s->rev_deleted & RevisionRecord::DELETED_TEXT
3165 ||
$s->rev_deleted & RevisionRecord::DELETED_USER
3168 return [ [
'notvisiblerev' ] ];
3174 RevisionStore::READ_LATEST
3176 if ( empty( $summary ) ) {
3177 if ( !$currentEditorForPublic ) {
3178 $summary =
wfMessage(
'revertpage-nouser' );
3183 $legacyTarget =
new Revision( $target );
3184 $targetEditorForPublic = $target->getUser( RevisionRecord::FOR_PUBLIC );
3187 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
3189 $targetEditorForPublic ? $targetEditorForPublic->getName() :
null,
3190 $currentEditorForPublic ? $currentEditorForPublic->getName() :
null,
3192 $contLang->timeanddate(
wfTimestamp( TS_MW,
$s->rev_timestamp ) ),
3194 $contLang->timeanddate( $current->getTimestamp() )
3196 if ( $summary instanceof
Message ) {
3197 $summary = $summary->params(
$args )->inContentLanguage()->text();
3203 $summary = trim( $summary );
3208 if ( $guser->isAllowed(
'minoredit' ) ) {
3212 if ( $bot && ( $guser->isAllowedAny(
'markbotedits',
'bot' ) ) ) {
3217 $currentContent = $current->getContent( SlotRecord::MAIN );
3218 $targetContent = $target->getContent( SlotRecord::MAIN );
3219 $changingContentModel = $targetContent->getModel() !== $currentContent->getModel();
3221 if ( in_array(
'mw-rollback', ChangeTags::getSoftwareTags() ) ) {
3222 $tags[] =
'mw-rollback';
3228 foreach ( $target->getSlots()->getSlots() as $slot ) {
3234 foreach ( $current->getSlotRoles() as $role ) {
3235 if ( !$target->hasSlot( $role ) ) {
3240 $updater->setOriginalRevisionId( $target->getId() );
3248 $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
3253 CommentStoreComment::newUnsavedComment( $summary ),
3260 if ( $bot && $guser->isAllowed(
'markbotedits' ) ) {
3267 $set[
'rc_patrolled'] = RecentChange::PRC_PATROLLED;
3270 if ( count( $set ) ) {
3271 $actorWhere = ActorMigration::newMigration()->getWhere(
3274 $current->getUser( RevisionRecord::RAW ),
3277 $dbw->update(
'recentchanges', $set,
3279 'rc_cur_id' => $current->getPageId(),
3280 'rc_timestamp > ' . $dbw->addQuotes(
$s->rev_timestamp ),
3281 $actorWhere[
'conds'],
3287 if ( !
$updater->wasSuccessful() ) {
3288 return $updater->getStatus()->getErrorsArray();
3293 $resultDetails = [
'current' => $legacyCurrent ];
3294 return [ [
'alreadyrolled',
3295 htmlspecialchars( $this->mTitle->getPrefixedText() ),
3296 htmlspecialchars( $fromP ),
3297 htmlspecialchars( $targetEditorForPublic ? $targetEditorForPublic->getName() :
'' )
3301 if ( $changingContentModel ) {
3305 $log->setPerformer( $guser );
3306 $log->setTarget( $this->mTitle );
3307 $log->setComment( $summary );
3308 $log->setParameters( [
3309 '4::oldmodel' => $currentContent->getModel(),
3310 '5::newmodel' => $targetContent->getModel(),
3313 $logId = $log->insert( $dbw );
3314 $log->publish( $logId );
3317 $revId =
$rev->getId();
3319 Hooks::run(
'ArticleRollbackComplete', [ $this, $guser, $legacyTarget, $legacyCurrent ] );
3322 'summary' => $summary,
3323 'current' => $legacyCurrent,
3324 'target' => $legacyTarget,
3348 $other = $title->getOtherPage();
3350 $other->purgeSquid();
3352 $title->touchLinks();
3353 $title->purgeSquid();
3354 $title->deleteTitleProtection();
3356 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
3359 DeferredUpdates::addUpdate(
3368 Category::newFromTitle( $title )->getID();
3383 $other = $title->getOtherPage();
3385 $other->purgeSquid();
3387 $title->touchLinks();
3388 $title->purgeSquid();
3390 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
3397 if ( $title->getNamespace() == NS_MEDIAWIKI ) {
3398 MessageCache::singleton()->updateMessageOverride( $title,
null );
3402 if ( $title->getNamespace() ==
NS_FILE ) {
3403 DeferredUpdates::addUpdate(
3412 $user->setNewtalk(
false );
3420 self::purgeInterwikiCheckKey( $title );
3434 $slotsChanged =
null
3438 if ( $slotsChanged ===
null || in_array( SlotRecord::MAIN, $slotsChanged ) ) {
3442 DeferredUpdates::addUpdate(
3448 DeferredUpdates::addUpdate(
3452 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
3455 $title->purgeSquid();
3460 $revid = $revision ? $revision->getId() :
null;
3461 DeferredUpdates::addCallableUpdate(
function () use ( $title, $revid ) {
3466 self::purgeInterwikiCheckKey( $title );
3483 DeferredUpdates::addCallableUpdate(
function () use ( $title ) {
3484 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
3489 $cache->makeGlobalKey(
'interwiki-page',
wfWikiID(), $title->getDBkey() )
3501 $id = $this->
getId();
3507 $res =
$dbr->select(
'categorylinks',
3508 [
'cl_to AS page_title, ' .
NS_CATEGORY .
' AS page_namespace' ],
3511 [
'cl_from' => $id ],
3525 $id = $this->
getId();
3532 $res =
$dbr->select( [
'categorylinks',
'page_props',
'page' ],
3534 [
'cl_from' => $id,
'pp_page=page_id',
'pp_propname' =>
'hiddencat',
3535 'page_namespace' =>
NS_CATEGORY,
'page_title=cl_to' ],
3538 if (
$res !==
false ) {
3539 foreach (
$res as $row ) {
3540 $result[] = Title::makeTitle(
NS_CATEGORY, $row->cl_to );
3569 $id = $id ?: $this->
getId();
3570 $type = MWNamespace::getCategoryLinkType( $this->
getTitle()->getNamespace() );
3572 $addFields = [
'cat_pages = cat_pages + 1' ];
3573 $removeFields = [
'cat_pages = cat_pages - 1' ];
3574 if (
$type !==
'page' ) {
3575 $addFields[] =
"cat_{$type}s = cat_{$type}s + 1";
3576 $removeFields[] =
"cat_{$type}s = cat_{$type}s - 1";
3581 if ( count( $added ) ) {
3582 $existingAdded = $dbw->selectFieldValues(
3585 [
'cat_title' => $added ],
3592 if ( count( $existingAdded ) ) {
3596 [
'cat_title' => $existingAdded ],
3601 $missingAdded = array_diff( $added, $existingAdded );
3602 if ( count( $missingAdded ) ) {
3604 foreach ( $missingAdded as $cat ) {
3606 'cat_title' => $cat,
3608 'cat_subcats' => (
$type ===
'subcat' ) ? 1 : 0,
3609 'cat_files' => (
$type ===
'file' ) ? 1 : 0,
3622 if ( count( $deleted ) ) {
3626 [
'cat_title' => $deleted ],
3631 foreach ( $added as $catName ) {
3632 $cat = Category::newFromName( $catName );
3633 Hooks::run(
'CategoryAfterPageAdded', [ $cat, $this ] );
3636 foreach ( $deleted as $catName ) {
3637 $cat = Category::newFromName( $catName );
3638 Hooks::run(
'CategoryAfterPageRemoved', [ $cat, $this, $id ] );
3640 DeferredUpdates::addCallableUpdate(
function () use ( $cat ) {
3641 $cat->refreshCountsIfEmpty();
3657 if ( !Hooks::run(
'OpportunisticLinksUpdate',
3658 [ $this, $this->mTitle, $parserOutput ]
3663 $config = RequestContext::getMain()->getConfig();
3666 'isOpportunistic' =>
true,
3670 if ( $this->mTitle->areRestrictionsCascading() ) {
3672 JobQueueGroup::singleton()->lazyPush(
3675 } elseif ( !$config->get(
'MiserMode' ) && $parserOutput->
hasDynamicContent() ) {
3685 $cache = ObjectCache::getLocalClusterInstance();
3686 $key =
$cache->makeKey(
'dynamic-linksupdate',
'last', $this->
getId() );
3688 if (
$cache->add( $key, time(), $ttl ) ) {
3689 JobQueueGroup::singleton()->lazyPush(
3708 wfDeprecated( __METHOD__ .
' without a RevisionRecord',
'1.32' );
3712 }
catch ( Exception $ex ) {
3717 wfDebug( __METHOD__ .
' failed to load current revision of page ' . $this->
getId() );
3724 wfDeprecated( __METHOD__ .
' with a Content object instead of a RevisionRecord',
'1.32' );
3726 $slotContent = [ SlotRecord::MAIN =>
$rev ];
3728 $slotContent = array_map(
function (
SlotRecord $slot ) {
3730 },
$rev->getSlots()->getSlots() );
3739 foreach ( $slotContent as $role =>
$content ) {
3742 $updates =
$handler->getDeletionUpdates(
3746 $allUpdates = array_merge( $allUpdates, $updates );
3749 $legacyUpdates =
$content->getDeletionUpdates( $this );
3752 $legacyUpdates = array_filter( $legacyUpdates,
function ( $update ) {
3756 $allUpdates = array_merge( $allUpdates, $legacyUpdates );
3759 Hooks::run(
'PageDeletionDataUpdates', [ $this->
getTitle(),
$rev, &$allUpdates ] );
3762 Hooks::run(
'WikiPageDeletionUpdates', [ $this,
$content, &$allUpdates ] );
3800 return $this->
getTitle()->getCanonicalURL();
3809 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3811 return $linkCache->getMutableCacheKeys(
$cache, $this->
getTitle() );
This list may contain false positives That usually means there is additional text with links below the first Each row contains links to the first and second as well as the first line of the second redirect text
bool $wgPageLanguageUseDB
Enable page language feature Allows setting page language in database.
$wgDeleteRevisionsBatchSize
Page deletions with > this number of revisions will use the job queue.
$wgCascadingRestrictionLevels
Restriction levels that can be used with cascading protection.
int $wgMultiContentRevisionSchemaMigrationStage
RevisionStore table schema migration stage (content, slots, content_models & slot_roles tables).
$wgUseAutomaticEditSummaries
If user doesn't specify any edit summary when making a an edit, MediaWiki will try to automatically c...
$wgSitename
Name of the site.
$wgPageCreationLog
Maintain a log of page creations at Special:Log/create?
$wgUseRCPatrol
Use RC Patrolling to check for vandalism (from recent changes and watchlists) New pages and new files...
$wgUseNPPatrol
Use new page patrolling to check new pages on Special:Newpages.
$wgArticleCountMethod
Method used to determine if a page in a content namespace should be counted as a valid article.
$wgAjaxEditStash
Have clients send edits to be prepared when filling in edit summaries.
$wgEnableScaryTranscluding
Enable interwiki transcluding.
int $wgCommentTableSchemaMigrationStage
Comment table schema migration stage.
$wgRCWatchCategoryMembership
Treat category membership changes as a RecentChange.
$wgContentHandlerUseDB
Set to false to disable use of the database fields introduced by the ContentHandler facility.
int $wgActorTableSchemaMigrationStage
Actor table schema migration stage.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfRandom()
Get a random decimal value between 0 and 1, in a way not likely to give duplicate values for any real...
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
wfIncrStats( $key, $count=1)
Increment a statistics counter.
wfReadOnly()
Check whether the wiki is in read-only mode.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfArrayDiff2( $a, $b)
Like array_diff( $a, $b ) except that it works with two-dimensional arrays.
wfReadOnlyReason()
Check if the site is in read-only mode and return the message if so.
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
static get(Title $title)
Create a new BacklinkCache or reuse any existing one.
getCacheExpiry()
Returns the number of seconds after which this object should expire.
Handles purging appropriate CDN URLs given a title (or titles)
Class to invalidate the HTML cache of all the pages linking to a given title.
static clearFileCache(Title $title)
Clear the file caches for a page for all actions.
static invalidateCache(Title $title, $revid=null)
Clear the info cache for a given Title.
Update object handling the cleanup of links tables after a page was deleted.
Class for creating new log entries and inserting them into the database.
A handle for managing updates for derived page data on edit, import, purge, etc.
setRcWatchCategoryMembership( $rcWatchCategoryMembership)
setArticleCountMethod( $articleCountMethod)
Controller-like object for creating and updating pages by creating new revisions.
The Message class provides methods which fulfil two basic services:
Set options of the Parser.
getStubThreshold()
Thumb size preferred by the user.
isSafeToCache()
Test whether these options are safe to cache.
hasDynamicContent()
Check whether the cache TTL was lowered due to dynamic content.
static newPrioritized(Title $title, array $params)
static newDynamic(Title $title, array $params)
static singleton()
Get a RepoGroup instance.
getContentHandler()
Returns the content handler appropriate for this revision's content model.
static newKnownCurrent(IDatabase $db, $pageIdOrTitle, $revId=0)
Load a revision based on a known page ID and current revision ID from the DB.
static newFromPageId( $pageId, $revId=0, $flags=0)
Load either the current, or a specified, revision that's attached to a given page ID.
static loadFromTimestamp( $db, $title, $timestamp)
Load the revision for the given title with the given timestamp.
static newNullRevision( $dbw, $pageId, $summary, $minor, $user=null)
Create a new null-revision for insertion into a page's history.
static getQueryInfo( $options=[])
Return the tables, fields, and join conditions to be selected to create a new revision object.
static newFromId( $id, $flags=0)
Load a page revision from a given revision ID number.
Database independant search index updater.
static newFromResult( $res)
Represents a title within MediaWiki.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
static newFromAnyId( $userId, $userName, $actorId)
Static factory method for creation from an ID, name, and/or actor ID.
static newFromId( $id)
Static factory method for creation from a given user ID.
static newFromIdentity(UserIdentity $identity)
Returns a User object corresponding to the given UserIdentity.
Multi-datacenter aware caching interface.
Special handling for category pages.
Special handling for file pages.
Class representing a MediaWiki article and history.
static newFromID( $id, $from='fromdb')
Constructor from a page id.
doUpdateRestrictions(array $limit, array $expiry, &$cascade, $reason, User $user, $tags=null)
Update the article's restriction field, and leave a log entry.
getContributors()
Get a list of users who have edited this article, not including the user who made the most recent rev...
doPurge()
Perform the actions of a page purging.
followRedirect()
Get the Title object or URL this page redirects to.
insertOn( $dbw, $pageId=null)
Insert a new empty page record for this article.
doDeleteArticleBatched( $reason, $suppress, User $deleter, $tags, $logsubtype, $immediate=false, $webRequestId=null)
Back-end article deletion.
updateCategoryCounts(array $added, array $deleted, $id=0)
Update all the appropriate counts in the category table, given that we've added the categories $added...
static purgeInterwikiCheckKey(Title $title)
#-
wasLoadedFrom( $from)
Checks whether the page data was loaded using the given database access mode (or better).
prepareContentForEdit(Content $content, $revision=null, User $user=null, $serialFormat=null, $useCache=true)
Prepare content which is about to be saved.
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
pageDataFromTitle( $dbr, $title, $options=[])
Fetch a page record matching the Title object's namespace and title using a sanitized title string.
checkFlags( $flags)
Check flags and add EDIT_NEW or EDIT_UPDATE to them as needed.
isLocal()
Whether this content displayed on this page comes from the local database.
getRevision()
Get the latest revision.
getUndoContent(Revision $undo, Revision $undoafter)
Get the content that needs to be saved in order to undo all revisions between $undo and $undoafter.
static onArticleEdit(Title $title, Revision $revision=null, $slotsChanged=null)
Purge caches on page update etc.
getLinksTimestamp()
Get the page_links_updated field.
getMinorEdit()
Returns true if last revision was marked as "minor edit".
clearCacheFields()
Clear the object cache fields.
clearPreparedEdit()
Clear the mPreparedEdit cache field, as may be needed by mutable content types.
getLatest()
Get the page_latest field.
PreparedEdit $mPreparedEdit
Map of cache fields (text, parser output, ect) for a proposed/new edit.
doViewUpdates(User $user, $oldid=0)
Do standard deferred updates after page view (existing or missing page)
updateIfNewerOn( $dbw, $revision)
If the given revision is newer than the currently set page_latest, update the page record.
__clone()
Makes sure that the mTitle object is cloned to the newly cloned WikiPage.
loadFromRow( $data, $from)
Load the object from a database row.
archiveRevisions( $dbw, $id, $suppress)
Archives revisions as part of page deletion.
supportsSections()
Returns true if this page's content model supports sections.
getRedirectTarget()
If this page is a redirect, get its target.
DerivedPageDataUpdater null $derivedDataUpdater
setTimestamp( $ts)
Set the page timestamp (use only to avoid DB queries)
protectDescriptionLog(array $limit, array $expiry)
Builds the description to serve as comment for the log entry.
getUser( $audience=Revision::FOR_PUBLIC, User $user=null)
makeParserOptions( $context)
Get parser options suitable for rendering the primary article wikitext.
pageData( $dbr, $conditions, $options=[])
Fetch a page record with the given conditions.
getSourceURL()
Get the source URL for the content on this page, typically the canonical URL, but may be a remote lin...
getOldestRevision()
Get the Revision object of the oldest revision.
isBatchedDelete( $safetyMargin=0)
Determines if deletion of this page would be batched (executed over time by the job queue) or not (co...
replaceSectionAtRev( $sectionId, Content $sectionContent, $sectionTitle='', $baseRevId=null)
setLastEdit(Revision $revision)
Set the latest revision.
updateRevisionOn( $dbw, $revision, $lastRevision=null, $lastRevIsRedirect=null)
Update the page record to point to a newly saved revision.
shouldCheckParserCache(ParserOptions $parserOptions, $oldId)
Should the parser cache be used?
loadLastEdit()
Loads everything except the text This isn't necessary for all uses, so it's only done if needed.
getDerivedDataUpdater(User $forUser=null, RevisionRecord $forRevision=null, RevisionSlotsUpdate $forUpdate=null, $forEdit=false)
Returns a DerivedPageDataUpdater for use with the given target revision or new content.
getUserText( $audience=Revision::FOR_PUBLIC, User $user=null)
getContentModel()
Returns the page's content model id (see the CONTENT_MODEL_XXX constants).
pageDataFromId( $dbr, $id, $options=[])
Fetch a page record matching the requested ID.
doEditUpdates(Revision $revision, User $user, array $options=[])
Do standard deferred updates after page edit.
insertRedirectEntry(Title $rt, $oldLatest=null)
Insert or update the redirect table entry for this page to indicate it redirects to $rt.
getCategories()
Returns a list of categories this page is a member of.
doDeleteUpdates( $id, Content $content=null, Revision $revision=null, User $user=null)
Do some database updates after deletion.
string $mTimestamp
Timestamp of the current revision or empty string if not loaded.
getHiddenCategories()
Returns a list of hidden categories this page is a member of.
doEditContent(Content $content, $summary, $flags=0, $originalRevId=false, User $user=null, $serialFormat=null, $tags=[], $undidRevId=0)
Change an existing article or create a new article.
getComment( $audience=Revision::FOR_PUBLIC, User $user=null)
getDeletionUpdates( $rev=null)
Returns a list of updates to be performed when this page is deleted.
static newFromRow( $row, $from='fromdb')
Constructor from a database row.
getAutoDeleteReason(&$hasHistory)
Auto-generates a deletion reason.
lockAndGetLatest()
Lock the page row for this title+id and return page_latest (or 0)
static flattenRestrictions( $limit)
Take an array of page restrictions and flatten it to a string suitable for insertion into the page_re...
getParserOutput(ParserOptions $parserOptions, $oldid=null, $forceParse=false)
Get a ParserOutput for the given ParserOptions and revision ID.
updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect=null)
Add row to the redirect table if this is a redirect, remove otherwise.
hasViewableContent()
Check if this page is something we're going to be showing some sort of sensible content for.
triggerOpportunisticLinksUpdate(ParserOutput $parserOutput)
Opportunistically enqueue link update jobs given fresh parser output if useful.
insertRedirect()
Insert an entry for this page into the redirect table if the content is a redirect.
static hasDifferencesOutsideMainSlot(Revision $a, Revision $b)
Helper method for checking whether two revisions have differences that go beyond the main slot.
getContent( $audience=Revision::FOR_PUBLIC, User $user=null)
Get the content of the current revision.
updateParserCache(array $options=[])
Update the parser cache.
static getQueryInfo()
Return the tables, fields, and join conditions to be selected to create a new page object.
int $mDataLoadedFrom
One of the READ_* constants.
static onArticleDelete(Title $title)
Clears caches when article is deleted.
newPageUpdater(User $user, RevisionSlotsUpdate $forUpdate=null)
Returns a PageUpdater for creating new revisions on this page (or creating the page).
replaceSectionContent( $sectionId, Content $sectionContent, $sectionTitle='', $edittime=null)
static selectFields()
Return the list of revision fields that should be selected to create a new page.
insertProtectNullRevision( $revCommentMsg, array $limit, array $expiry, $cascade, $reason, $user=null)
Insert a new null revision for this page.
getTitle()
Get the title object of the article.
isRedirect()
Tests if the article content represents a redirect.
static onArticleCreate(Title $title)
The onArticle*() functions are supposed to be a kind of hooks which should be called whenever any of ...
doDeleteArticleReal( $reason, $suppress=false, $u1=null, $u2=null, &$error='', User $deleter=null, $tags=[], $logsubtype='delete', $immediate=false)
Back-end article deletion Deletes the article with database consistency, writes logs,...
commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser, $tags=null)
Backend implementation of doRollback(), please refer there for parameter and return value documentati...
getRedirectURL( $rt)
Get the Title object or URL to use for a redirect.
doSecondaryDataUpdates(array $options=[])
Do secondary data updates (such as updating link tables).
loadPageData( $from='fromdb')
Load the object from a given source by title.
checkTouched()
Loads page_touched and returns a value indicating if it should be used.
isCountable( $editInfo=false)
Determine whether a page would be suitable for being counted as an article in the site_stats table ba...
doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user, $tags=null)
Roll back the most recent consecutive set of edits to a page from the same user; fails if there are n...
getContentHandler()
Returns the ContentHandler instance to be used to deal with the content of this WikiPage.
getRevisionRecord()
Get the latest revision.
getWikiDisplayName()
The display name for the site this content come from.
static convertSelectType( $type)
Convert 'fromdb', 'fromdbmaster' and 'forupdate' to READ_* constants.
getCreator( $audience=Revision::FOR_PUBLIC, User $user=null)
Get the User object of the user who created the page.
getMutableCacheKeys(WANObjectCache $cache)
protectDescription(array $limit, array $expiry)
Builds the description to serve as comment for the edit.
getTouched()
Get the page_touched field.
__construct(Title $title)
Constructor and clear the article.
doDeleteArticle( $reason, $suppress=false, $u1=null, $u2=null, &$error='', User $user=null, $immediate=false)
Same as doDeleteArticleReal(), but returns a simple boolean.
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
namespace being checked & $result
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account incomplete not yet checked for validity & $retval
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
namespace and then decline to actually register it file or subcat img or subcat $title
this hook is for auditing only RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist & $tables
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation use $formDescriptor instead default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "<div ...>$1</div>"). - flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException':Called before an exception(or PHP error) is logged. This is meant for integration with external error aggregation services
Status::newGood()` to allow deletion, and then `return false` from the hook function. Ensure you consume the 'ChangeTagAfterDelete' hook to carry out custom deletion actions. $tag:name of the tag $user:user initiating the action & $status:Status object. See above. 'ChangeTagsListActive':Allows you to nominate which of the tags your extension uses are in active use. & $tags:list of all active tags. Append to this array. 'ChangeTagsAfterUpdateTags':Called after tags have been updated with the ChangeTags::updateTags function. Params:$addedTags:tags effectively added in the update $removedTags:tags effectively removed in the update $prevTags:tags that were present prior to the update $rc_id:recentchanges table id $rev_id:revision table id $log_id:logging table id $params:tag params $rc:RecentChange being tagged when the tagging accompanies the action, or null $user:User who performed the tagging when the tagging is subsequent to the action, or null 'ChangeTagsAllowedAdd':Called when checking if a user can add tags to a change. & $allowedTags:List of all the tags the user is allowed to add. Any tags the user wants to add( $addTags) that are not in this array will cause it to fail. You may add or remove tags to this array as required. $addTags:List of tags user intends to add. $user:User who is adding the tags. 'ChangeUserGroups':Called before user groups are changed. $performer:The User who will perform the change $user:The User whose groups will be changed & $add:The groups that will be added & $remove:The groups that will be removed 'Collation::factory':Called if $wgCategoryCollation is an unknown collation. $collationName:Name of the collation in question & $collationObject:Null. Replace with a subclass of the Collation class that implements the collation given in $collationName. 'ConfirmEmailComplete':Called after a user 's email has been confirmed successfully. $user:user(object) whose email is being confirmed 'ContentAlterParserOutput':Modify parser output for a given content object. Called by Content::getParserOutput after parsing has finished. Can be used for changes that depend on the result of the parsing but have to be done before LinksUpdate is called(such as adding tracking categories based on the rendered HTML). $content:The Content to render $title:Title of the page, as context $parserOutput:ParserOutput to manipulate 'ContentGetParserOutput':Customize parser output for a given content object, called by AbstractContent::getParserOutput. May be used to override the normal model-specific rendering of page content. $content:The Content to render $title:Title of the page, as context $revId:The revision ID, as context $options:ParserOptions for rendering. To avoid confusing the parser cache, the output can only depend on parameters provided to this hook function, not on global state. $generateHtml:boolean, indicating whether full HTML should be generated. If false, generation of HTML may be skipped, but other information should still be present in the ParserOutput object. & $output:ParserOutput, to manipulate or replace 'ContentHandlerDefaultModelFor':Called when the default content model is determined for a given title. May be used to assign a different model for that title. $title:the Title in question & $model:the model name. Use with CONTENT_MODEL_XXX constants. 'ContentHandlerForModelID':Called when a ContentHandler is requested for a given content model name, but no entry for that model exists in $wgContentHandlers. Note:if your extension implements additional models via this hook, please use GetContentModels hook to make them known to core. $modeName:the requested content model name & $handler:set this to a ContentHandler object, if desired. 'ContentModelCanBeUsedOn':Called to determine whether that content model can be used on a given page. This is especially useful to prevent some content models to be used in some special location. $contentModel:ID of the content model in question $title:the Title in question. & $ok:Output parameter, whether it is OK to use $contentModel on $title. Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok. 'ContribsPager::getQueryInfo':Before the contributions query is about to run & $pager:Pager object for contributions & $queryInfo:The query for the contribs Pager 'ContribsPager::reallyDoQuery':Called before really executing the query for My Contributions & $data:an array of results of all contribs queries $pager:The ContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'ContributionsLineEnding':Called before a contributions HTML line is finished $page:SpecialPage object for contributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'ContributionsToolLinks':Change tool links above Special:Contributions $id:User identifier $title:User page title & $tools:Array of tool links $specialPage:SpecialPage instance for context and services. Can be either SpecialContributions or DeletedContributionsPage. Extensions should type hint against a generic SpecialPage though. 'ConvertContent':Called by AbstractContent::convert when a conversion to another content model is requested. Handler functions that modify $result should generally return false to disable further attempts at conversion. $content:The Content object to be converted. $toModel:The ID of the content model to convert to. $lossy: boolean indicating whether lossy conversion is allowed. & $result:Output parameter, in case the handler function wants to provide a converted Content object. Note that $result->getContentModel() must return $toModel. 'ContentSecurityPolicyDefaultSource':Modify the allowed CSP load sources. This affects all directives except for the script directive. If you want to add a script source, see ContentSecurityPolicyScriptSource hook. & $defaultSrc:Array of Content-Security-Policy allowed sources $policyConfig:Current configuration for the Content-Security-Policy header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'ContentSecurityPolicyDirectives':Modify the content security policy directives. Use this only if ContentSecurityPolicyDefaultSource and ContentSecurityPolicyScriptSource do not meet your needs. & $directives:Array of CSP directives $policyConfig:Current configuration for the CSP header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'ContentSecurityPolicyScriptSource':Modify the allowed CSP script sources. Note that you also have to use ContentSecurityPolicyDefaultSource if you want non-script sources to be loaded from whatever you add. & $scriptSrc:Array of CSP directives $policyConfig:Current configuration for the CSP header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'CustomEditor':When invoking the page editor Return true to allow the normal editor to be used, or false if implementing a custom editor, e.g. for a special namespace, etc. $article:Article being edited $user:User performing the edit 'DatabaseOraclePostInit':Called after initialising an Oracle database $db:the DatabaseOracle object 'DeletedContribsPager::reallyDoQuery':Called before really executing the query for Special:DeletedContributions Similar to ContribsPager::reallyDoQuery & $data:an array of results of all contribs queries $pager:The DeletedContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'DeletedContributionsLineEnding':Called before a DeletedContributions HTML line is finished. Similar to ContributionsLineEnding $page:SpecialPage object for DeletedContributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'DeleteUnknownPreferences':Called by the cleanupPreferences.php maintenance script to build a WHERE clause with which to delete preferences that are not known about. This hook is used by extensions that have dynamically-named preferences that should not be deleted in the usual cleanup process. For example, the Gadgets extension creates preferences prefixed with 'gadget-', and so anything with that prefix is excluded from the deletion. &where:An array that will be passed as the $cond parameter to IDatabase::select() to determine what will be deleted from the user_properties table. $db:The IDatabase object, useful for accessing $db->buildLike() etc. 'DifferenceEngineAfterLoadNewText':called in DifferenceEngine::loadNewText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before returning true from this function. $differenceEngine:DifferenceEngine object 'DifferenceEngineLoadTextAfterNewContentIsLoaded':called in DifferenceEngine::loadText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before checking if the variable 's value is null. This hook can be used to inject content into said class member variable. $differenceEngine:DifferenceEngine object 'DifferenceEngineMarkPatrolledLink':Allows extensions to change the "mark as
patrolled" link which is shown both on the diff header as well as on the bottom of a page, usually wrapped in a span element which has class="patrollink". $differenceEngine:DifferenceEngine object & $markAsPatrolledLink:The "mark as patrolled" link HTML(string) $rcid:Recent change ID(rc_id) for this change(int) 'DifferenceEngineMarkPatrolledRCID':Allows extensions to possibly change the rcid parameter. For example the rcid might be set to zero due to the user being the same as the performer of the change but an extension might still want to show it under certain conditions. & $rcid:rc_id(int) of the change or 0 $differenceEngine:DifferenceEngine object $change:RecentChange object $user:User object representing the current user 'DifferenceEngineNewHeader':Allows extensions to change the $newHeader variable, which contains information about the new revision, such as the revision 's author, whether the revision was marked as a minor edit or not, etc. $differenceEngine:DifferenceEngine object & $newHeader:The string containing the various #mw-diff-otitle[1-5] divs, which include things like revision author info, revision comment, RevisionDelete link and more $formattedRevisionTools:Array containing revision tools, some of which may have been injected with the DiffRevisionTools hook $nextlink:String containing the link to the next revision(if any) $status
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable modifiable after all normalizations have been except for the $wgMaxImageArea check set to true or false to override the $wgMaxImageArea check result gives extension the possibility to transform it themselves $handler
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
const SCHEMA_COMPAT_WRITE_OLD
const SCHEMA_COMPAT_WRITE_NEW
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback function
Base interface for content objects.
Interface for database access objects.
const READ_LOCKING
Constants for object loading bitfield flags (higher => higher QoS)
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
$page->newPageUpdater($user) $updater
if(count( $args)< 1) $job