127 $this->mTitle = clone $this->mTitle;
139 $ns = $title->getNamespace();
142 throw new MWException(
"NS_MEDIA is a virtual namespace; use NS_FILE." );
144 throw new MWException(
"Invalid or virtual namespace $ns given." );
148 if ( !Hooks::run(
'WikiPageFactory', [ $title, &$page ] ) ) {
176 public static function newFromID( $id, $from =
'fromdb' ) {
182 $from = self::convertSelectType( $from );
184 $pageQuery = self::getQueryInfo();
185 $row = $db->selectRow(
186 $pageQuery[
'tables'], $pageQuery[
'fields'], [
'page_id' => $id ], __METHOD__,
187 [], $pageQuery[
'joins']
192 return self::newFromRow( $row, $from );
206 public static function newFromRow( $row, $from =
'fromdb' ) {
207 $page = self::factory( Title::newFromRow( $row ) );
208 $page->loadFromRow( $row, $from );
223 return self::READ_LATEST;
225 return self::READ_LOCKING;
236 return MediaWikiServices::getInstance()->getRevisionStore();
243 return MediaWikiServices::getInstance()->getRevisionRenderer();
250 return MediaWikiServices::getInstance()->getSlotRoleRegistry();
257 return MediaWikiServices::getInstance()->getParserCache();
264 return MediaWikiServices::getInstance()->getDBLoadBalancer();
287 return ContentHandler::getForModelID( $this->getContentModel() );
295 return $this->mTitle;
303 $this->mDataLoaded =
false;
304 $this->mDataLoadedFrom = self::READ_NONE;
315 $this->mRedirectTarget =
null;
316 $this->mLastRevision =
null;
317 $this->mTouched =
'19700101000000';
318 $this->mLinksUpdated =
'19700101000000';
319 $this->mTimestamp =
'';
320 $this->mIsRedirect =
false;
321 $this->mLatest =
false;
334 $this->mPreparedEdit =
false;
358 'page_links_updated',
364 $fields[] =
'page_content_model';
368 $fields[] =
'page_lang';
387 'tables' => [
'page' ],
397 'page_links_updated',
405 $ret[
'fields'][] =
'page_content_model';
409 $ret[
'fields'][] =
'page_lang';
423 $pageQuery = self::getQueryInfo();
428 Hooks::run(
'ArticlePageDataBefore', [
429 &$wikiPage, &$pageQuery[
'fields'], &$pageQuery[
'tables'], &$pageQuery[
'joins']
432 $row =
$dbr->selectRow(
433 $pageQuery[
'tables'],
434 $pageQuery[
'fields'],
441 Hooks::run(
'ArticlePageDataAfter', [ &$wikiPage, &$row ] );
457 'page_namespace' => $title->getNamespace(),
458 'page_title' => $title->getDBkey() ],
$options );
486 $from = self::convertSelectType( $from );
487 if (
is_int( $from ) && $from <= $this->mDataLoadedFrom ) {
493 list( $index, $opts ) = DBAccessObjectUtils::getDBOptions( $from );
495 $db = $loadBalancer->getConnection( $index );
500 && $loadBalancer->getServerCount() > 1
501 && $loadBalancer->hasOrMadeRecentMasterChanges()
503 $from = self::READ_LATEST;
504 list( $index, $opts ) = DBAccessObjectUtils::getDBOptions( $from );
505 $db = $loadBalancer->getConnection( $index );
531 $from = self::convertSelectType( $from );
538 if (
is_int( $from ) && $from <= $this->mDataLoadedFrom ) {
557 $lc = MediaWikiServices::getInstance()->getLinkCache();
558 $lc->clearLink( $this->mTitle );
561 $lc->addGoodLinkObjFromRow( $this->mTitle,
$data );
563 $this->mTitle->loadFromRow(
$data );
566 $this->mTitle->loadRestrictions(
$data->page_restrictions );
571 $this->mIsRedirect =
intval(
$data->page_is_redirect );
575 if ( $this->mLastRevision && $this->mLastRevision->getId() != $this->mLatest ) {
576 $this->mLastRevision =
null;
577 $this->mTimestamp =
'';
580 $lc->addBadLinkObj( $this->mTitle );
582 $this->mTitle->loadFromRow(
false );
589 $this->mDataLoaded =
true;
590 $this->mDataLoadedFrom = self::convertSelectType( $from );
597 if ( !$this->mDataLoaded ) {
607 if ( !$this->mDataLoaded ) {
610 return $this->mId > 0;
622 return $this->mTitle->isKnown();
631 if ( !$this->mDataLoaded ) {
635 return (
bool)$this->mIsRedirect;
650 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
652 return $cache->getWithSetCallback(
653 $cache->makeKey(
'page-content-model', $this->getLatest() ),
659 return $rev->getContentModel();
661 $title = $this->mTitle->getPrefixedDBkey();
662 wfWarn(
"Page $title exists but has no (visible) revisions!" );
663 return $this->mTitle->getContentModel();
670 return $this->mTitle->getContentModel();
678 if ( !$this->mDataLoaded ) {
681 return ( $this->mId && !$this->mIsRedirect );
689 if ( !$this->mDataLoaded ) {
692 return $this->mTouched;
700 if ( !$this->mDataLoaded ) {
703 return $this->mLinksUpdated;
711 if ( !$this->mDataLoaded ) {
714 return (
int)$this->mLatest;
723 $rev = $this->mTitle->getFirstRevision();
725 $rev = $this->mTitle->getFirstRevision( Title::GAID_FOR_UPDATE );
735 if ( $this->mLastRevision !==
null ) {
744 if ( $this->mDataLoadedFrom == self::READ_LOCKING ) {
754 }
elseif ( $this->mDataLoadedFrom == self::READ_LATEST ) {
758 $flags = Revision::READ_LATEST;
775 $this->mLastRevision = $revision;
785 if ( $this->mLastRevision ) {
786 return $this->mLastRevision;
797 if ( $this->mLastRevision ) {
798 return $this->mLastRevision->getRevisionRecord();
818 if ( $this->mLastRevision ) {
819 return $this->mLastRevision->getContent( $audience, $user );
829 if ( !$this->mTimestamp ) {
856 if ( $this->mLastRevision ) {
857 return $this->mLastRevision->getUser( $audience, $user );
876 $userName = $revision->getUserText( $audience, $user );
894 if ( $this->mLastRevision ) {
895 return $this->mLastRevision->getUserText( $audience, $user );
913 if ( $this->mLastRevision ) {
914 return $this->mLastRevision->getComment( $audience, $user );
927 if ( $this->mLastRevision ) {
928 return $this->mLastRevision->isMinor();
947 if ( !$this->mTitle->isContentPage() ) {
972 $hasLinks = (
bool)count( $editInfo->output->getLinks() );
985 return $content->isCountable( $hasLinks );
996 if ( !$this->mTitle->isRedirect() ) {
1000 if ( $this->mRedirectTarget !==
null ) {
1001 return $this->mRedirectTarget;
1006 $row =
$dbr->selectRow(
'redirect',
1007 [
'rd_namespace',
'rd_title',
'rd_fragment',
'rd_interwiki' ],
1008 [
'rd_from' => $this->
getId() ],
1013 if ( $row && !
is_null( $row->rd_fragment ) && !is_null( $row->rd_interwiki ) ) {
1017 if ( $row->rd_namespace ==
NS_MEDIA ) {
1020 $namespace = $row->rd_namespace;
1022 $this->mRedirectTarget = Title::makeTitle(
1023 $namespace, $row->rd_title,
1024 $row->rd_fragment, $row->rd_interwiki
1026 return $this->mRedirectTarget;
1031 return $this->mRedirectTarget;
1051 DeferredUpdates::addCallableUpdate(
1052 function () use ( $retval, $latest ) {
1055 DeferredUpdates::POSTSEND,
1069 $dbw->startAtomic( __METHOD__ );
1072 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
1073 $truncatedFragment = $contLang->truncateForDatabase( $rt->getFragment(), 255 );
1077 'rd_from' => $this->
getId(),
1078 'rd_namespace' => $rt->getNamespace(),
1079 'rd_title' => $rt->getDBkey(),
1080 'rd_fragment' => $truncatedFragment,
1081 'rd_interwiki' => $rt->getInterwiki(),
1085 'rd_namespace' => $rt->getNamespace(),
1086 'rd_title' => $rt->getDBkey(),
1087 'rd_fragment' => $truncatedFragment,
1088 'rd_interwiki' => $rt->getInterwiki(),
1094 $dbw->endAtomic( __METHOD__ );
1118 if ( $rt->isExternal() ) {
1119 if ( $rt->isLocal() ) {
1123 $source = $this->mTitle->getFullURL(
'redirect=no' );
1124 return $rt->getFullURL( [
'rdfrom' =>
$source ] );
1132 if ( $rt->isSpecialPage() ) {
1136 if ( $rt->isValidRedirectTarget() ) {
1137 return $rt->getFullURL();
1156 $actorMigration = ActorMigration::newMigration();
1157 $actorQuery = $actorMigration->getJoin(
'rev_user' );
1162 'user_id' => $actorQuery[
'fields'][
'rev_user'],
1163 'user_name' => $actorQuery[
'fields'][
'rev_user_text'],
1164 'actor_id' => $actorQuery[
'fields'][
'rev_actor'],
1165 'user_real_name' =>
'MIN(user_real_name)',
1166 'timestamp' =>
'MAX(rev_timestamp)',
1169 $conds = [
'rev_page' => $this->
getId() ];
1176 $conds[] =
'NOT(' . $actorMigration->getWhere(
$dbr,
'rev_user', $user )[
'conds'] .
')';
1179 $conds[] =
"{$dbr->bitAnd( 'rev_deleted', Revision::DELETED_USER )} = 0";
1182 'user' => [
'LEFT JOIN', $actorQuery[
'fields'][
'rev_user'] .
' = user_id' ],
1183 ] + $actorQuery[
'joins'];
1186 'GROUP BY' => [ $fields[
'user_id'], $fields[
'user_name'] ],
1187 'ORDER BY' =>
'timestamp DESC',
1204 && ( $oldId ===
null || $oldId === 0 || $oldId === $this->
getLatest() )
1224 ParserOptions $parserOptions, $oldid =
null, $forceParse =
false
1229 if ( $useParserCache && !$parserOptions->
isSafeToCache() ) {
1230 throw new InvalidArgumentException(
1231 'The supplied ParserOptions are not safe to cache. Fix the options or set $forceParse = true.'
1236 ': using parser cache: ' . ( $useParserCache ?
'yes' :
'no' ) .
"\n" );
1241 if ( $useParserCache ) {
1243 ->get( $this, $parserOptions );
1244 if ( $parserOutput !==
false ) {
1245 return $parserOutput;
1249 if ( $oldid ===
null || $oldid === 0 ) {
1256 return $pool->getParserOutput();
1271 DeferredUpdates::addCallableUpdate(
1272 function () use ( $user, $oldid ) {
1273 Hooks::run(
'PageViewUpdates', [ $this, $user ] );
1275 $user->clearNotification( $this->mTitle, $oldid );
1277 DeferredUpdates::PRESEND
1291 if ( !Hooks::run(
'ArticlePurge', [ &$wikiPage ] ) ) {
1295 $this->mTitle->invalidateCache();
1300 DeferredUpdates::addUpdate(
1302 DeferredUpdates::PRESEND
1305 if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
1306 $messageCache = MessageCache::singleton();
1307 $messageCache->updateMessageOverride( $this->mTitle, $this->
getContent() );
1330 $pageIdForInsert = $pageId ? [
'page_id' => $pageId ] : [];
1334 'page_namespace' => $this->mTitle->getNamespace(),
1335 'page_title' => $this->mTitle->getDBkey(),
1336 'page_restrictions' =>
'',
1337 'page_is_redirect' => 0,
1340 'page_touched' => $dbw->timestamp(),
1343 ] + $pageIdForInsert,
1348 if ( $dbw->affectedRows() > 0 ) {
1349 $newid = $pageId ? (
int)$pageId : $dbw->insertId();
1351 $this->mTitle->resetArticleID( $newid );
1375 $lastRevIsRedirect =
null
1384 if ( (
int)$revision->getId() === 0 ) {
1385 throw new InvalidArgumentException(
1386 __METHOD__ .
': Revision has ID ' .
var_export( $revision->getId(), 1 )
1390 $content = $revision->getContent();
1394 $conditions = [
'page_id' => $this->
getId() ];
1396 if ( !
is_null( $lastRevision ) ) {
1401 $revId = $revision->getId();
1402 Assert::parameter( $revId > 0,
'$revision->getId()',
'must be > 0' );
1405 'page_latest' => $revId,
1406 'page_touched' => $dbw->timestamp( $revision->getTimestamp() ),
1407 'page_is_new' => ( $lastRevision === 0 ) ? 1 : 0,
1408 'page_is_redirect' => $rt !==
null ? 1 : 0,
1413 $row[
'page_content_model'] = $revision->getContentModel();
1416 $dbw->update(
'page',
1421 $result = $dbw->affectedRows() > 0;
1425 $this->mLatest = $revision->getId();
1426 $this->mIsRedirect = (
bool)$rt;
1428 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1429 $linkCache->addGoodLinkObj(
1435 $revision->getContentModel()
1457 $isRedirect = !
is_null( $redirectTitle );
1459 if ( !$isRedirect && $lastRevIsRedirect ===
false ) {
1463 if ( $isRedirect ) {
1467 $where = [
'rd_from' => $this->
getId() ];
1468 $dbw->delete(
'redirect', $where, __METHOD__ );
1475 return ( $dbw->affectedRows() != 0 );
1489 $row = $dbw->selectRow(
1490 [
'revision',
'page' ],
1491 [
'rev_id',
'rev_timestamp',
'page_is_redirect' ],
1493 'page_id' => $this->
getId(),
1494 'page_latest=rev_id' ],
1498 if (
wfTimestamp( TS_MW, $row->rev_timestamp ) >= $revision->getTimestamp() ) {
1501 $prev = $row->rev_id;
1502 $lastRevIsRedirect = (
bool)$row->page_is_redirect;
1506 $lastRevIsRedirect =
null;
1527 $aSlots = $a->getRevisionRecord()->getSlots();
1528 $bSlots = $b->getRevisionRecord()->getSlots();
1529 $changedRoles = $aSlots->getRolesWithDifferentContent( $bSlots );
1531 return ( $changedRoles !== [ SlotRecord::MAIN ] && $changedRoles !== [] );
1548 if ( self::hasDifferencesOutsideMainSlot( $undo, $undoafter ) ) {
1586 $sectionId,
Content $sectionContent, $sectionTitle =
'', $edittime =
null
1589 if ( $edittime && $sectionId !==
'new' ) {
1597 && $lb->getServerCount() > 1
1598 && $lb->hasOrMadeRecentMasterChanges()
1604 $baseRevId =
$rev->getId();
1608 return $this->
replaceSectionAtRev( $sectionId, $sectionContent, $sectionTitle, $baseRevId );
1625 $sectionTitle =
'', $baseRevId =
null
1627 if (
strval( $sectionId ) ===
'' ) {
1632 throw new MWException(
"sections not supported for content model " .
1637 if (
is_null( $baseRevId ) || $sectionId ===
'new' ) {
1642 wfDebug( __METHOD__ .
" asked for bogus section (page: " .
1643 $this->
getId() .
"; section: $sectionId)\n" );
1647 $oldContent =
$rev->getContent();
1650 if ( !$oldContent ) {
1651 wfDebug( __METHOD__ .
": no page text\n" );
1655 $newContent = $oldContent->replaceSection( $sectionId, $sectionContent, $sectionTitle );
1694 JobQueueGroup::singleton(),
1695 MessageCache::singleton(),
1696 MediaWikiServices::getInstance()->getContentLanguage(),
1697 MediaWikiServices::getInstance()->getDBLoadBalancerFactory()
1734 User $forUser =
null,
1739 if ( !$forRevision && !$forUpdate ) {
1742 $this->derivedDataUpdater =
null;
1745 if ( $this->derivedDataUpdater && !$this->derivedDataUpdater->isContentPrepared() ) {
1749 $this->derivedDataUpdater =
null;
1756 if ( $this->derivedDataUpdater
1757 && !$this->derivedDataUpdater->isReusableFor(
1761 $forEdit ? $this->getLatest() :
null
1764 $this->derivedDataUpdater =
null;
1767 if ( !$this->derivedDataUpdater ) {
1771 return $this->derivedDataUpdater;
1872 User $user =
null, $serialFormat =
null, $tags = [], $undidRevId = 0
1877 $summary = CommentStoreComment::newUnsavedComment(
trim( $summary ) );
1887 if ( ( $flags &
EDIT_MINOR ) && !$user->isAllowed(
'minoredit' ) ) {
1892 $slotsUpdate->modifyContent( SlotRecord::MAIN,
$content );
1899 $updater->setOriginalRevisionId( $originalRevId );
1900 $updater->setUndidRevisionId( $undidRevId );
1907 if ( $needsPatrol && $this->
getTitle()->userCan(
'autopatrol', $user ) ) {
1908 $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
1925 $this->mLatest = $revRec->getId();
1948 if ( $this->
getTitle()->isConversionTable() ) {
1951 $options->disableContentConversion();
1981 $serialFormat =
null,
1994 if ( $revid !==
null ) {
1995 wfDeprecated( __METHOD__ .
' with $revision = revision ID',
'1.25' );
1997 $revision = $store->getRevisionById( $revid, Revision::READ_LATEST );
2002 $revision = $revision->getRevisionRecord();
2005 $slots = RevisionSlotsUpdate::newFromContent( [ SlotRecord::MAIN =>
$content ] );
2008 if ( !
$updater->isUpdatePrepared() ) {
2009 $updater->prepareContent( $user, $slots, $useCache );
2015 'causeAction' =>
'prepare-edit',
2016 'causeAgent' => $user->getName(),
2022 return $updater->getPreparedEdit();
2054 'causeAction' =>
'edit-page',
2055 'causeAgent' => $user->getName(),
2082 if ( !$revision || !$revision->getId() ) {
2083 LoggerFactory::getInstance(
'wikipage' )->info(
2084 __METHOD__ .
'called with ' . ( $revision ?
'unsaved' :
'no' ) .
' revision'
2124 if ( !$revision || !$revision->getId() ) {
2125 LoggerFactory::getInstance(
'wikipage' )->info(
2126 __METHOD__ .
'called with ' . ( $revision ?
'unsaved' :
'no' ) .
' revision'
2152 &$cascade, $reason,
User $user, $tags =
null
2161 $this->mTitle->loadRestrictions(
null, Title::READ_LATEST );
2162 $restrictionTypes = $this->mTitle->getRestrictionTypes();
2163 $id = $this->
getId();
2170 Title::purgeExpiredRestrictions();
2174 $isProtected =
false;
2180 foreach ( $restrictionTypes as $action ) {
2181 if ( !
isset( $expiry[$action] ) || $expiry[$action] === $dbw->getInfinity() ) {
2182 $expiry[$action] =
'infinity';
2184 if ( !
isset( $limit[$action] ) ) {
2185 $limit[$action] =
'';
2186 }
elseif ( $limit[$action] !=
'' ) {
2191 $current = implode(
'', $this->mTitle->getRestrictions( $action ) );
2192 if ( $current !=
'' ) {
2193 $isProtected =
true;
2196 if ( $limit[$action] != $current ) {
2198 }
elseif ( $limit[$action] !=
'' ) {
2202 if ( $this->mTitle->getRestrictionExpiry( $action ) != $expiry[$action] ) {
2208 if ( !$changed && $protect && $this->mTitle->areRestrictionsCascading() != $cascade ) {
2214 return Status::newGood();
2218 $revCommentMsg =
'unprotectedarticle-comment';
2219 $logAction =
'unprotect';
2220 }
elseif ( $isProtected ) {
2221 $revCommentMsg =
'modifiedarticleprotection-comment';
2222 $logAction =
'modify';
2224 $revCommentMsg =
'protectedarticle-comment';
2225 $logAction =
'protect';
2228 $logRelationsValues = [];
2229 $logRelationsField =
null;
2230 $logParamsDetails = [];
2233 $nullRevision =
null;
2239 if ( !Hooks::run(
'ArticleProtect', [ &$wikiPage, &$user, $limit, $reason ] ) ) {
2240 return Status::newGood();
2244 $editrestriction =
isset( $limit[
'edit'] )
2245 ? [ $limit[
'edit'] ]
2246 : $this->mTitle->getRestrictions(
'edit' );
2247 foreach (
array_keys( $editrestriction,
'sysop' ) as $key ) {
2248 $editrestriction[$key] =
'editprotected';
2250 foreach (
array_keys( $editrestriction,
'autoconfirmed' ) as $key ) {
2251 $editrestriction[$key] =
'editsemiprotected';
2255 foreach (
array_keys( $cascadingRestrictionLevels,
'sysop' ) as $key ) {
2256 $cascadingRestrictionLevels[$key] =
'editprotected';
2258 foreach (
array_keys( $cascadingRestrictionLevels,
'autoconfirmed' ) as $key ) {
2259 $cascadingRestrictionLevels[$key] =
'editsemiprotected';
2263 if ( !
array_intersect( $editrestriction, $cascadingRestrictionLevels ) ) {
2278 if ( $nullRevision ===
null ) {
2279 return Status::newFatal(
'no-null-revision', $this->mTitle->getPrefixedText() );
2282 $logRelationsField =
'pr_id';
2285 foreach ( $limit as $action => $restrictions ) {
2287 'page_restrictions',
2290 'pr_type' => $action
2294 if ( $restrictions !=
'' ) {
2295 $cascadeValue = ( $cascade && $action ==
'edit' ) ? 1 : 0;
2297 'page_restrictions',
2300 'pr_type' => $action,
2301 'pr_level' => $restrictions,
2302 'pr_cascade' => $cascadeValue,
2303 'pr_expiry' => $dbw->encodeExpiry( $expiry[$action] )
2307 $logRelationsValues[] = $dbw->insertId();
2308 $logParamsDetails[] = [
2310 'level' => $restrictions,
2311 'expiry' => $expiry[$action],
2312 'cascade' => (
bool)$cascadeValue,
2320 [
'page_restrictions' =>
'' ],
2321 [
'page_id' => $id ],
2328 Hooks::run(
'NewRevisionFromEditComplete',
2329 [ $this, $nullRevision, $latest, $user ] );
2330 Hooks::run(
'ArticleProtectComplete', [ &$wikiPage, &$user, $limit, $reason ] );
2335 if ( $limit[
'create'] !=
'' ) {
2336 $commentFields = CommentStore::getStore()->insert( $dbw,
'pt_reason', $reason );
2337 $dbw->replace(
'protected_titles',
2338 [ [
'pt_namespace',
'pt_title' ] ],
2340 'pt_namespace' => $this->mTitle->getNamespace(),
2341 'pt_title' => $this->mTitle->getDBkey(),
2342 'pt_create_perm' => $limit[
'create'],
2343 'pt_timestamp' => $dbw->timestamp(),
2344 'pt_expiry' => $dbw->encodeExpiry( $expiry[
'create'] ),
2345 'pt_user' => $user->getId(),
2346 ] + $commentFields, __METHOD__
2348 $logParamsDetails[] = [
2350 'level' => $limit[
'create'],
2351 'expiry' => $expiry[
'create'],
2354 $dbw->delete(
'protected_titles',
2356 'pt_namespace' => $this->mTitle->getNamespace(),
2357 'pt_title' => $this->mTitle->getDBkey()
2363 $this->mTitle->flushRestrictions();
2366 if ( $logAction ==
'unprotect' ) {
2379 $logEntry->setTarget( $this->mTitle );
2380 $logEntry->setComment( $reason );
2381 $logEntry->setPerformer( $user );
2382 $logEntry->setParameters(
$params );
2383 if ( !
is_null( $nullRevision ) ) {
2384 $logEntry->setAssociatedRevId( $nullRevision->getId() );
2386 $logEntry->setTags( $tags );
2387 if ( $logRelationsField !==
null && count( $logRelationsValues ) ) {
2388 $logEntry->setRelations( [ $logRelationsField => $logRelationsValues ] );
2390 $logId = $logEntry->insert();
2391 $logEntry->publish( $logId );
2393 return Status::newGood( $logId );
2408 array $expiry, $cascade, $reason, $user =
null
2415 $this->mTitle->getPrefixedText(),
2416 $user ? $user->getName() :
''
2417 )->inContentLanguage()->text();
2419 $editComment .=
wfMessage(
'colon-separator' )->inContentLanguage()->text() . $reason;
2422 if ( $protectDescription ) {
2423 $editComment .=
wfMessage(
'word-separator' )->inContentLanguage()->text();
2424 $editComment .=
wfMessage(
'parentheses' )->params( $protectDescription )
2425 ->inContentLanguage()->text();
2428 $editComment .=
wfMessage(
'word-separator' )->inContentLanguage()->text();
2429 $editComment .=
wfMessage(
'brackets' )->params(
2430 wfMessage(
'protect-summary-cascade' )->inContentLanguage()->
text()
2431 )->inContentLanguage()->text();
2436 $nullRev->insertOn( $dbw );
2439 $oldLatest = $nullRev->getParentId();
2451 if ( $expiry !=
'infinity' ) {
2452 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
2455 $contLang->timeanddate( $expiry,
false,
false ),
2456 $contLang->date( $expiry,
false,
false ),
2457 $contLang->time( $expiry,
false,
false )
2458 )->inContentLanguage()->text();
2460 return wfMessage(
'protect-expiry-indefinite' )
2461 ->inContentLanguage()->text();
2473 $protectDescription =
'';
2475 foreach (
array_filter( $limit ) as $action => $restrictions ) {
2476 # $action is one of $wgRestrictionTypes = [ 'create', 'edit', 'move', 'upload' ].
2477 # All possible message keys are listed here for easier grepping:
2478 # * restriction-create
2479 # * restriction-edit
2480 # * restriction-move
2481 # * restriction-upload
2482 $actionText =
wfMessage(
'restriction-' . $action )->inContentLanguage()->text();
2483 # $restrictions is one of $wgRestrictionLevels = [ '', 'autoconfirmed', 'sysop' ],
2484 # with '' filtered out. All possible message keys are listed below:
2485 # * protect-level-autoconfirmed
2486 # * protect-level-sysop
2487 $restrictionsText =
wfMessage(
'protect-level-' . $restrictions )
2488 ->inContentLanguage()->text();
2492 if ( $protectDescription !==
'' ) {
2493 $protectDescription .=
wfMessage(
'word-separator' )->inContentLanguage()->text();
2495 $protectDescription .=
wfMessage(
'protect-summary-desc' )
2496 ->params( $actionText, $restrictionsText, $expiryText )
2497 ->inContentLanguage()->text();
2515 $protectDescriptionLog =
'';
2517 $dirMark = MediaWikiServices::getInstance()->getContentLanguage()->getDirMark();
2518 foreach (
array_filter( $limit ) as $action => $restrictions ) {
2520 $protectDescriptionLog .=
2522 "[$action=$restrictions] ($expiryText)";
2525 return trim( $protectDescriptionLog );
2539 throw new MWException( __METHOD__ .
' given non-array restriction set' );
2545 foreach (
array_filter( $limit ) as $action => $restrictions ) {
2546 $bits[] =
"$action=$restrictions";
2549 return implode(
':', $bits );
2594 $reason, $suppress =
false, $u1 =
null, $u2 =
null, &$error =
'',
User $user =
null,
2598 [],
'delete', $immediate );
2627 $reason, $suppress =
false, $u1 =
null, $u2 =
null, &$error =
'',
User $deleter =
null,
2628 $tags = [], $logsubtype =
'delete', $immediate =
false
2642 if ( !Hooks::run(
'ArticleDelete',
2643 [ &$wikiPage, &$deleter, &$reason, &$error, &
$status, $suppress ]
2647 $status->fatal(
'delete-hook-aborted' );
2653 $logsubtype, $immediate );
2665 $reason, $suppress,
User $deleter, $tags,
2666 $logsubtype, $immediate =
false, $webRequestId =
null
2673 $dbw->startAtomic( __METHOD__ );
2676 $id = $this->
getId();
2682 if ( $id == 0 || $this->
getLatest() != $lockedLatest ) {
2683 $dbw->endAtomic( __METHOD__ );
2685 $status->error(
'cannotdelete',
2699 }
catch ( Exception $ex ) {
2700 wfLogWarning( __METHOD__ .
': failed to load content during deletion! '
2701 . $ex->getMessage() );
2708 $explictTrxLogged =
false;
2711 if ( $done || !$immediate ) {
2714 $dbw->endAtomic( __METHOD__ );
2715 if ( $dbw->explicitTrxActive() ) {
2717 if ( !$explictTrxLogged ) {
2718 $explictTrxLogged =
true;
2719 LoggerFactory::getInstance(
'wfDebug' )->debug(
2720 'explicit transaction active in ' . __METHOD__ .
' while deleting {title}', [
2721 'title' => $this->
getTitle()->getText(),
2726 if ( $dbw->trxLevel() ) {
2729 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
2730 $lbFactory->waitForReplication();
2731 $dbw->startAtomic( __METHOD__ );
2736 $dbw->endAtomic( __METHOD__ );
2739 'wikiPageId' => $id,
2740 'requestId' => $webRequestId ?? WebRequest::getRequestId(),
2741 'reason' => $reason,
2742 'suppress' => $suppress,
2743 'userId' => $deleter->getId(),
2749 JobQueueGroup::singleton()->push(
$job );
2751 $status->warning(
'delete-scheduled',
2761 $archivedRevisionCount = (
int)$dbw->selectField(
2762 'archive',
'COUNT(*)',
2764 'ar_namespace' => $this->getTitle()->getNamespace(),
2765 'ar_title' => $this->
getTitle()->getDBkey(),
2772 $logTitle = clone $this->mTitle;
2773 $wikiPageBeforeDelete = clone
$this;
2776 $dbw->delete(
'page', [
'page_id' => $id ], __METHOD__ );
2779 $logtype = $suppress ?
'suppress' :
'delete';
2782 $logEntry->setPerformer( $deleter );
2783 $logEntry->setTarget( $logTitle );
2784 $logEntry->setComment( $reason );
2785 $logEntry->setTags( $tags );
2786 $logid = $logEntry->insert();
2788 $dbw->onTransactionPreCommitOrIdle(
2789 function () use ( $logEntry, $logid ) {
2791 $logEntry->publish( $logid );
2796 $dbw->endAtomic( __METHOD__ );
2800 Hooks::run(
'ArticleDeleteComplete', [
2801 &$wikiPageBeforeDelete,
2807 $archivedRevisionCount
2812 $cache = MediaWikiServices::getInstance()->getMainObjectStash();
2813 $key =
$cache->makeKey(
'page-recent-delete',
md5( $logTitle->getPrefixedText() ) );
2814 $cache->set( $key, 1, $cache::TTL_DAY );
2834 $namespace = $this->
getTitle()->getNamespace();
2835 $dbKey = $this->
getTitle()->getDBkey();
2837 $commentStore = CommentStore::getStore();
2838 $actorMigration = ActorMigration::newMigration();
2860 $dbw->lockForUpdate(
2863 [
'revision',
'revision_comment_temp',
'revision_actor_temp' ]
2865 [
'rev_page' => $id ],
2878 $revQuery[
'fields'][] =
'rev_content_model';
2879 $revQuery[
'fields'][] =
'rev_content_format';
2885 $res = $dbw->select(
2888 [
'rev_page' => $id ],
2902 foreach (
$res as $row ) {
2908 $comment = $commentStore->getComment(
'rev_comment', $row );
2911 'ar_namespace' => $namespace,
2912 'ar_title' => $dbKey,
2913 'ar_timestamp' => $row->rev_timestamp,
2914 'ar_minor_edit' => $row->rev_minor_edit,
2915 'ar_rev_id' => $row->rev_id,
2916 'ar_parent_id' => $row->rev_parent_id,
2925 'ar_len' => $row->rev_len,
2926 'ar_page_id' => $id,
2927 'ar_deleted' => $suppress ?
$bitfield : $row->rev_deleted,
2928 'ar_sha1' => $row->rev_sha1,
2929 ] + $commentStore->insert( $dbw,
'ar_comment', $comment )
2930 + $actorMigration->getInsertValues( $dbw,
'ar_user', $user );
2933 $rowInsert[
'ar_text_id'] = $row->rev_text_id;
2936 $rowInsert[
'ar_content_model'] = $row->rev_content_model;
2937 $rowInsert[
'ar_content_format'] = $row->rev_content_format;
2942 $revids[] = $row->rev_id;
2946 if ( (
int)$row->rev_user === 0 && IP::isValid( $row->rev_user_text ) ) {
2947 $ipRevIds[] = $row->rev_id;
2952 if ( count( $revids ) > 0 ) {
2954 $dbw->insert(
'archive', $rowsInsert, __METHOD__ );
2956 $dbw->delete(
'revision', [
'rev_id' => $revids ], __METHOD__ );
2957 $dbw->delete(
'revision_comment_temp', [
'revcomment_rev' => $revids ], __METHOD__ );
2959 $dbw->delete(
'revision_actor_temp', [
'revactor_rev' => $revids ], __METHOD__ );
2963 if ( count( $ipRevIds ) > 0 ) {
2964 $dbw->delete(
'ip_changes', [
'ipc_rev_id' => $ipRevIds ], __METHOD__ );
2982 'page_id' => $this->
getId(),
2985 'page_namespace' => $this->
getTitle()->getNamespace(),
2986 'page_title' => $this->
getTitle()->getDBkey()
3008 if ( $id !== $this->
getId() ) {
3009 throw new InvalidArgumentException(
'Mismatching page ID' );
3014 }
catch ( Exception $ex ) {
3021 DeferredUpdates::addUpdate( SiteStatsUpdate::factory(
3022 [
'edits' => 1,
'articles' => -$countable,
'pages' => -1 ]
3027 $revision ? $revision->getRevisionRecord() :
$content
3029 foreach ( $updates as $update ) {
3030 DeferredUpdates::addUpdate( $update );
3033 $causeAgent = $user ? $user->getName() :
'unknown';
3035 LinksUpdate::queueRecursiveJobsForTable(
3036 $this->mTitle,
'templatelinks',
'delete-page', $causeAgent );
3038 if ( $this->mTitle->getNamespace() ==
NS_FILE ) {
3039 LinksUpdate::queueRecursiveJobsForTable(
3040 $this->mTitle,
'imagelinks',
'delete-page', $causeAgent );
3044 self::onArticleDelete( $this->mTitle );
3045 ResourceLoaderWikiModule::invalidateModuleCache(
3049 WikiMap::getCurrentWikiDbDomain()->
getId()
3056 DeferredUpdates::addUpdate(
new SearchUpdate( $id, $this->mTitle ) );
3089 $fromP, $summary, $token, $bot, &$resultDetails,
User $user, $tags =
null
3091 $resultDetails =
null;
3094 $editErrors = $this->mTitle->getUserPermissionsErrors(
'edit', $user );
3095 $rollbackErrors = $this->mTitle->getUserPermissionsErrors(
'rollback', $user );
3098 if ( !$user->matchEditToken( $token,
'rollback' ) ) {
3099 $errors[] = [
'sessionfailure' ];
3102 if ( $user->pingLimiter(
'rollback' ) || $user->pingLimiter() ) {
3103 $errors[] = [
'actionthrottledtext' ];
3107 if ( !empty( $errors ) ) {
3111 return $this->
commitRollback( $fromP, $summary, $bot, $resultDetails, $user, $tags );
3135 &$resultDetails,
User $guser, $tags =
null
3142 return [ [
'readonlytext' ] ];
3148 $current =
$updater->grabParentRevision();
3152 return [ [
'notanarticle' ] ];
3155 $currentEditorForPublic = $current->getUser( RevisionRecord::FOR_PUBLIC );
3156 $legacyCurrent =
new Revision( $current );
3161 if ( $from !== ( $currentEditorForPublic ? $currentEditorForPublic->getName() :
'' ) ) {
3163 return [ [
'alreadyrolled',
3166 htmlspecialchars( $currentEditorForPublic ? $currentEditorForPublic->getName() :
'' )
3172 $actorWhere = ActorMigration::newMigration()->getWhere(
3175 $current->getUser( RevisionRecord::RAW )
3178 $s = $dbw->selectRow(
3179 [
'revision' ] + $actorWhere[
'tables'],
3180 [
'rev_id',
'rev_timestamp',
'rev_deleted' ],
3182 'rev_page' => $current->getPageId(),
3183 'NOT(' . $actorWhere[
'conds'] .
')',
3187 'USE INDEX' => [
'revision' =>
'page_timestamp' ],
3188 'ORDER BY' =>
'rev_timestamp DESC'
3190 $actorWhere[
'joins']
3192 if (
$s ===
false ) {
3194 return [ [
'cantrollback' ] ];
3195 }
elseif (
$s->rev_deleted & RevisionRecord::DELETED_TEXT
3196 ||
$s->rev_deleted & RevisionRecord::DELETED_USER
3199 return [ [
'notvisiblerev' ] ];
3205 RevisionStore::READ_LATEST
3207 if ( empty( $summary ) ) {
3208 if ( !$currentEditorForPublic ) {
3209 $summary =
wfMessage(
'revertpage-nouser' );
3214 $legacyTarget =
new Revision( $target );
3215 $targetEditorForPublic = $target->getUser( RevisionRecord::FOR_PUBLIC );
3218 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
3220 $targetEditorForPublic ? $targetEditorForPublic->getName() :
null,
3221 $currentEditorForPublic ? $currentEditorForPublic->getName() :
null,
3223 $contLang->timeanddate(
wfTimestamp( TS_MW,
$s->rev_timestamp ) ),
3225 $contLang->timeanddate( $current->getTimestamp() )
3227 if ( $summary instanceof
Message ) {
3228 $summary = $summary->params(
$args )->inContentLanguage()->text();
3234 $summary =
trim( $summary );
3239 if ( $guser->isAllowed(
'minoredit' ) ) {
3243 if ( $bot && ( $guser->isAllowedAny(
'markbotedits',
'bot' ) ) ) {
3248 $currentContent = $current->getContent( SlotRecord::MAIN );
3249 $targetContent = $target->getContent( SlotRecord::MAIN );
3250 $changingContentModel = $targetContent->getModel() !== $currentContent->getModel();
3253 $tags[] =
'mw-rollback';
3259 foreach ( $target->getSlots()->getSlots() as $slot ) {
3265 foreach ( $current->getSlotRoles() as $role ) {
3266 if ( !$target->hasSlot( $role ) ) {
3271 $updater->setOriginalRevisionId( $target->getId() );
3279 $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
3284 CommentStoreComment::newUnsavedComment( $summary ),
3291 if ( $bot && $guser->isAllowed(
'markbotedits' ) ) {
3298 $set[
'rc_patrolled'] = RecentChange::PRC_AUTOPATROLLED;
3301 if ( count( $set ) ) {
3302 $actorWhere = ActorMigration::newMigration()->getWhere(
3305 $current->getUser( RevisionRecord::RAW ),
3308 $dbw->update(
'recentchanges', $set,
3310 'rc_cur_id' => $current->getPageId(),
3311 'rc_timestamp > ' . $dbw->addQuotes(
$s->rev_timestamp ),
3312 $actorWhere[
'conds'],
3318 if ( !
$updater->wasSuccessful() ) {
3319 return $updater->getStatus()->getErrorsArray();
3325 return [ [
'alreadyrolled',
3328 htmlspecialchars( $targetEditorForPublic ? $targetEditorForPublic->getName() :
'' )
3332 if ( $changingContentModel ) {
3336 $log->setPerformer( $guser );
3337 $log->setTarget( $this->mTitle );
3338 $log->setComment( $summary );
3339 $log->setParameters( [
3340 '4::oldmodel' => $currentContent->getModel(),
3341 '5::newmodel' => $targetContent->getModel(),
3344 $logId = $log->insert( $dbw );
3345 $log->publish( $logId );
3348 $revId =
$rev->getId();
3350 Hooks::run(
'ArticleRollbackComplete', [ $this, $guser, $legacyTarget, $legacyCurrent ] );
3353 'summary' => $summary,
3379 $other = $title->getOtherPage();
3381 $other->purgeSquid();
3383 $title->touchLinks();
3384 $title->purgeSquid();
3385 $title->deleteTitleProtection();
3387 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
3390 DeferredUpdates::addUpdate(
3399 Category::newFromTitle( $title )->getID();
3414 $other = $title->getOtherPage();
3416 $other->purgeSquid();
3418 $title->touchLinks();
3419 $title->purgeSquid();
3421 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
3428 if ( $title->getNamespace() == NS_MEDIAWIKI ) {
3429 MessageCache::singleton()->updateMessageOverride( $title,
null );
3433 if ( $title->getNamespace() ==
NS_FILE ) {
3434 DeferredUpdates::addUpdate(
3443 $user->setNewtalk(
false );
3451 self::purgeInterwikiCheckKey( $title );
3465 $slotsChanged =
null
3469 if ( $slotsChanged ===
null ||
in_array( SlotRecord::MAIN, $slotsChanged ) ) {
3473 DeferredUpdates::addUpdate(
3479 DeferredUpdates::addUpdate(
3483 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
3486 $title->purgeSquid();
3491 $revid = $revision ? $revision->getId() :
null;
3492 DeferredUpdates::addCallableUpdate(
function () use ( $title, $revid ) {
3497 self::purgeInterwikiCheckKey( $title );
3514 DeferredUpdates::addCallableUpdate(
function () use ( $title ) {
3515 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
3522 WikiMap::getCurrentWikiDbDomain()->getId(),
3536 $id = $this->
getId();
3542 $res =
$dbr->select(
'categorylinks',
3543 [
'cl_to AS page_title, ' .
NS_CATEGORY .
' AS page_namespace' ],
3546 [
'cl_from' => $id ],
3560 $id = $this->
getId();
3567 $res =
$dbr->select( [
'categorylinks',
'page_props',
'page' ],
3569 [
'cl_from' => $id,
'pp_page=page_id',
'pp_propname' =>
'hiddencat',
3570 'page_namespace' =>
NS_CATEGORY,
'page_title=cl_to' ],
3573 if (
$res !==
false ) {
3574 foreach (
$res as $row ) {
3575 $result[] = Title::makeTitle(
NS_CATEGORY, $row->cl_to );
3604 $id = $id ?: $this->
getId();
3605 $type = MWNamespace::getCategoryLinkType( $this->
getTitle()->getNamespace() );
3607 $addFields = [
'cat_pages = cat_pages + 1' ];
3608 $removeFields = [
'cat_pages = cat_pages - 1' ];
3609 if (
$type !==
'page' ) {
3610 $addFields[] =
"cat_{$type}s = cat_{$type}s + 1";
3611 $removeFields[] =
"cat_{$type}s = cat_{$type}s - 1";
3616 if ( count( $added ) ) {
3617 $existingAdded = $dbw->selectFieldValues(
3620 [
'cat_title' => $added ],
3627 if ( count( $existingAdded ) ) {
3631 [
'cat_title' => $existingAdded ],
3636 $missingAdded =
array_diff( $added, $existingAdded );
3637 if ( count( $missingAdded ) ) {
3639 foreach ( $missingAdded as $cat ) {
3641 'cat_title' => $cat,
3643 'cat_subcats' => (
$type ===
'subcat' ) ? 1 : 0,
3644 'cat_files' => (
$type ===
'file' ) ? 1 : 0,
3657 if ( count( $deleted ) ) {
3661 [
'cat_title' => $deleted ],
3666 foreach ( $added as $catName ) {
3667 $cat = Category::newFromName( $catName );
3668 Hooks::run(
'CategoryAfterPageAdded', [ $cat, $this ] );
3671 foreach ( $deleted as $catName ) {
3672 $cat = Category::newFromName( $catName );
3673 Hooks::run(
'CategoryAfterPageRemoved', [ $cat, $this, $id ] );
3675 DeferredUpdates::addCallableUpdate(
function () use ( $cat ) {
3676 $cat->refreshCountsIfEmpty();
3692 if ( !Hooks::run(
'OpportunisticLinksUpdate',
3693 [ $this, $this->mTitle, $parserOutput ]
3698 $config = RequestContext::getMain()->getConfig();
3701 'isOpportunistic' =>
true,
3705 if ( $this->mTitle->areRestrictionsCascading() ) {
3707 JobQueueGroup::singleton()->lazyPush(
3720 $cache = ObjectCache::getLocalClusterInstance();
3721 $key =
$cache->makeKey(
'dynamic-linksupdate',
'last', $this->
getId() );
3723 if (
$cache->add( $key, time(), $ttl ) ) {
3724 JobQueueGroup::singleton()->lazyPush(
3743 wfDeprecated( __METHOD__ .
' without a RevisionRecord',
'1.32' );
3747 }
catch ( Exception $ex ) {
3752 wfDebug( __METHOD__ .
' failed to load current revision of page ' . $this->
getId() );
3759 wfDeprecated( __METHOD__ .
' with a Content object instead of a RevisionRecord',
'1.32' );
3761 $slotContent = [ SlotRecord::MAIN =>
$rev ];
3765 },
$rev->getSlots()->getSlots() );
3774 foreach ( $slotContent as $role =>
$content ) {
3777 $updates =
$handler->getDeletionUpdates(
3781 $allUpdates =
array_merge( $allUpdates, $updates );
3784 $legacyUpdates =
$content->getDeletionUpdates( $this );
3787 $legacyUpdates =
array_filter( $legacyUpdates,
function ( $update ) {
3791 $allUpdates =
array_merge( $allUpdates, $legacyUpdates );
3794 Hooks::run(
'PageDeletionDataUpdates', [ $this->
getTitle(),
$rev, &$allUpdates ] );
3797 Hooks::run(
'WikiPageDeletionUpdates', [ $this,
$content, &$allUpdates ] );
3835 return $this->
getTitle()->getCanonicalURL();
3844 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3846 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
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two and(2) offer you this license which gives you legal permission to copy
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.
$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 in the domain of [0, 1), in a way not likely to give duplicate values for ...
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.
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)
int false $mLatest
False means "not loaded".
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
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that When $user is not it can be in the form of< username >< more info > e g for bot passwords intended to be added to log contexts Fields it might only if the login was with a bot password 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
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
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that When $user is not null
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
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
$data
Utility to generate mapping file used in mw.Title (phpCharToUpper.json)
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