* @return Title|null The new object, or null on an error
*/
public static function newFromID( $id, $flags = 0 ) {
- $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
$row = $db->selectRow(
'page',
self::getSelectFields(),
if ( !count( $ids ) ) {
return [];
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$res = $dbr->select(
'page',
* @return Title|null An object representing the article, or null if no such article was found
*/
public static function nameOf( $id ) {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$s = $dbr->selectRow(
'page',
/**
* Callback for usort() to do title sorts by (namespace, title)
*
- * @param Title $a
- * @param Title $b
+ * @param LinkTarget $a
+ * @param LinkTarget $b
*
* @return int Result of string comparison, or namespace comparison
*/
- public static function compare( $a, $b ) {
+ public static function compare( LinkTarget $a, LinkTarget $b ) {
if ( $a->getNamespace() == $b->getNamespace() ) {
return strcmp( $a->getText(), $b->getText() );
} else {
* @param string $action Action that permission needs to be checked for
* @param User $user User to check
* @param string $rigor One of (quick,full,secure)
- * - quick : does cheap permission checks from slaves (usable for GUI creation)
- * - full : does cheap and expensive checks possibly from a slave
+ * - quick : does cheap permission checks from replica DBs (usable for GUI creation)
+ * - full : does cheap and expensive checks possibly from a replica DB
* - secure : does cheap and expensive checks, using the master as needed
* @param array $ignoreErrors Array of Strings Set this to a list of message keys
* whose corresponding errors may be ignored.
* @return array List of errors
*/
private function checkUserBlock( $action, $user, $errors, $rigor, $short ) {
+ global $wgEmailConfirmToEdit, $wgBlockDisablesLogin;
// Account creation blocks handled at userlogin.
// Unblocking handled in SpecialUnblock
if ( $rigor === 'quick' || in_array( $action, [ 'createaccount', 'unblock' ] ) ) {
return $errors;
}
- global $wgEmailConfirmToEdit;
+ // Optimize for a very common case
+ if ( $action === 'read' && !$wgBlockDisablesLogin ) {
+ return $errors;
+ }
if ( $wgEmailConfirmToEdit && !$user->isEmailConfirmed() ) {
$errors[] = [ 'confirmedittext' ];
# If the user is allowed to read pages, he is allowed to read all pages
$whitelisted = true;
} elseif ( $this->isSpecial( 'Userlogin' )
- || $this->isSpecial( 'ChangePassword' )
|| $this->isSpecial( 'PasswordReset' )
+ || $this->isSpecial( 'Userlogout' )
) {
# Always grant access to the login page.
# Even anons need to be able to log in.
* @param string $action Action that permission needs to be checked for
* @param User $user User to check
* @param string $rigor One of (quick,full,secure)
- * - quick : does cheap permission checks from slaves (usable for GUI creation)
- * - full : does cheap and expensive checks possibly from a slave
+ * - quick : does cheap permission checks from replica DBs (usable for GUI creation)
+ * - full : does cheap and expensive checks possibly from a replica DB
* - secure : does cheap and expensive checks, using the master as needed
* @param bool $short Set this to true to stop after the first permission error.
* @return array Array of arrays of the arguments to wfMessage to explain permissions problems.
$checks = [
'checkPermissionHooks',
'checkReadPermissions',
+ 'checkUserBlock', // for wgBlockDisablesLogin
];
# Don't call checkSpecialsAndNSPermissions or checkCSSandJSPermissions
# here as it will lead to duplicate error messages. This is okay to do
}
if ( $this->mTitleProtection === null ) {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$res = $dbr->select(
'protected_titles',
[
return [ $this->mHasCascadingRestrictions, $pagerestrictions ];
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
if ( $this->getNamespace() == NS_FILE ) {
$tables = [ 'imagelinks', 'page_restrictions' ];
return $this->mCascadeRestriction;
}
- /**
- * Loads a string into mRestrictions array
- *
- * @param ResultWrapper $res Resource restrictions as an SQL result.
- * @param string $oldFashionedRestrictions Comma-separated list of page
- * restrictions from page table (pre 1.10)
- */
- private function loadRestrictionsFromResultWrapper( $res, $oldFashionedRestrictions = null ) {
- $rows = [];
-
- foreach ( $res as $row ) {
- $rows[] = $row;
- }
-
- $this->loadRestrictionsFromRows( $rows, $oldFashionedRestrictions );
- }
-
/**
* Compiles list of active page restrictions from both page table (pre 1.10)
* and page_restrictions table for this existing page.
* restrictions from page table (pre 1.10)
*/
public function loadRestrictionsFromRows( $rows, $oldFashionedRestrictions = null ) {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$restrictionTypes = $this->getRestrictionTypes();
* restrictions from page table (pre 1.10)
*/
public function loadRestrictions( $oldFashionedRestrictions = null ) {
- if ( !$this->mRestrictionsLoaded ) {
- $dbr = wfGetDB( DB_SLAVE );
- if ( $this->exists() ) {
- $res = $dbr->select(
- 'page_restrictions',
- [ 'pr_type', 'pr_expiry', 'pr_level', 'pr_cascade' ],
- [ 'pr_page' => $this->getArticleID() ],
- __METHOD__
- );
+ if ( $this->mRestrictionsLoaded ) {
+ return;
+ }
- $this->loadRestrictionsFromResultWrapper( $res, $oldFashionedRestrictions );
- } else {
- $title_protection = $this->getTitleProtection();
-
- if ( $title_protection ) {
- $now = wfTimestampNow();
- $expiry = $dbr->decodeExpiry( $title_protection['expiry'] );
-
- if ( !$expiry || $expiry > $now ) {
- // Apply the restrictions
- $this->mRestrictionsExpiry['create'] = $expiry;
- $this->mRestrictions['create'] = explode( ',', trim( $title_protection['permission'] ) );
- } else { // Get rid of the old restrictions
- $this->mTitleProtection = false;
- }
- } else {
- $this->mRestrictionsExpiry['create'] = 'infinity';
+ $id = $this->getArticleID();
+ if ( $id ) {
+ $cache = ObjectCache::getMainWANInstance();
+ $rows = $cache->getWithSetCallback(
+ // Page protections always leave a new null revision
+ $cache->makeKey( 'page-restrictions', $id, $this->getLatestRevID() ),
+ $cache::TTL_DAY,
+ function ( $curValue, &$ttl, array &$setOpts ) {
+ $dbr = wfGetDB( DB_REPLICA );
+
+ $setOpts += Database::getCacheSetOptions( $dbr );
+
+ return iterator_to_array(
+ $dbr->select(
+ 'page_restrictions',
+ [ 'pr_type', 'pr_expiry', 'pr_level', 'pr_cascade' ],
+ [ 'pr_page' => $this->getArticleID() ],
+ __METHOD__
+ )
+ );
+ }
+ );
+
+ $this->loadRestrictionsFromRows( $rows, $oldFashionedRestrictions );
+ } else {
+ $title_protection = $this->getTitleProtection();
+
+ if ( $title_protection ) {
+ $now = wfTimestampNow();
+ $expiry = wfGetDB( DB_REPLICA )->decodeExpiry( $title_protection['expiry'] );
+
+ if ( !$expiry || $expiry > $now ) {
+ // Apply the restrictions
+ $this->mRestrictionsExpiry['create'] = $expiry;
+ $this->mRestrictions['create'] =
+ explode( ',', trim( $title_protection['permission'] ) );
+ } else { // Get rid of the old restrictions
+ $this->mTitleProtection = false;
}
- $this->mRestrictionsLoaded = true;
+ } else {
+ $this->mRestrictionsExpiry['create'] = 'infinity';
}
+ $this->mRestrictionsLoaded = true;
}
}
return [];
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$conds['page_namespace'] = $this->getNamespace();
$conds[] = 'page_title ' . $dbr->buildLike( $this->getDBkey() . '/', $dbr->anyString() );
$options = [];
if ( $this->getNamespace() < 0 ) {
$n = 0;
} else {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$n = $dbr->selectField( 'archive', 'COUNT(*)',
[ 'ar_namespace' => $this->getNamespace(), 'ar_title' => $this->getDBkey() ],
if ( $this->getNamespace() < 0 ) {
return false;
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$deleted = (bool)$dbr->selectField( 'archive', '1',
[ 'ar_namespace' => $this->getNamespace(), 'ar_title' => $this->getDBkey() ],
__METHOD__
if ( count( $options ) > 0 ) {
$db = wfGetDB( DB_MASTER );
} else {
- $db = wfGetDB( DB_SLAVE );
+ $db = wfGetDB( DB_REPLICA );
}
$res = $db->select(
return [];
}
- $db = wfGetDB( DB_SLAVE );
+ $db = wfGetDB( DB_REPLICA );
$blNamespace = "{$prefix}_namespace";
$blTitle = "{$prefix}_title";
return [];
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$res = $dbr->select(
[ 'page', 'pagelinks' ],
[ 'pl_namespace', 'pl_title' ],
return $data;
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$res = $dbr->select(
'categorylinks',
* @return int|bool Old revision ID, or false if none exists
*/
public function getPreviousRevisionID( $revId, $flags = 0 ) {
- $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
$revId = $db->selectField( 'revision', 'rev_id',
[
'rev_page' => $this->getArticleID( $flags ),
* @return int|bool Next revision ID, or false if none exists
*/
public function getNextRevisionID( $revId, $flags = 0 ) {
- $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
$revId = $db->selectField( 'revision', 'rev_id',
[
'rev_page' => $this->getArticleID( $flags ),
public function getFirstRevision( $flags = 0 ) {
$pageId = $this->getArticleID( $flags );
if ( $pageId ) {
- $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
$row = $db->selectRow( 'revision', Revision::selectFields(),
[ 'rev_page' => $pageId ],
__METHOD__,
* @return bool
*/
public function isNewPage() {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
return (bool)$dbr->selectField( 'page', 'page_is_new', $this->pageCond(), __METHOD__ );
}
}
if ( $this->mIsBigDeletion === null ) {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$revCount = $dbr->selectRowCount(
'revision',
}
if ( $this->mEstimateRevisions === null ) {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$this->mEstimateRevisions = $dbr->estimateRowCount( 'revision', '*',
[ 'rev_page' => $this->getArticleID() ], __METHOD__ );
}
if ( !$old || !$new ) {
return 0; // nothing to compare
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$conds = [
'rev_page' => $this->getArticleID(),
'rev_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $old->getTimestamp() ) ),
}
return $authors;
}
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$res = $dbr->select( 'revision', 'DISTINCT rev_user_text',
[
'rev_page' => $this->getArticleID(),
$conds + [ 'page_touched < ' . $dbw->addQuotes( $dbTimestamp ) ],
$fname
);
+ MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $this );
}
),
DeferredUpdates::PRESEND
*/
public function getTouched( $db = null ) {
if ( $db === null ) {
- $db = wfGetDB( DB_SLAVE );
+ $db = wfGetDB( DB_REPLICA );
}
$touched = $db->selectField( 'page', 'page_touched', $this->pageCond(), __METHOD__ );
return $touched;
public function getRedirectsHere( $ns = null ) {
$redirs = [];
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$where = [
'rd_namespace' => $this->getNamespace(),
'rd_title' => $this->getDBkey(),