require_once( dirname( __FILE__ ) . '/normal/UtfNormal.php' );
}
+/**
+ * @deprecated This used to be a define, but was moved to
+ * Title::GAID_FOR_UPDATE in 1.17. This will probably be removed in 1.18
+ */
+define( 'GAID_FOR_UPDATE', Title::GAID_FOR_UPDATE );
+
/**
* Represents a title within MediaWiki.
* Optionally may contain an interwiki designation or namespace.
* This will only return the very next target, useful for
* the redirect table and other checks that don't need full recursion
*
- * @param $text \type{\string} Text with possible redirect
- * @return \type{Title} The corresponding Title
+ * @param $text String: Text with possible redirect
+ * @return Title: The corresponding Title
*/
public static function newFromRedirect( $text ) {
return self::newFromRedirectInternal( $text );
// and URL-decode links
if ( strpos( $m[1], '%' ) !== false ) {
// Match behavior of inline link parsing here;
- // don't interpret + as " " most of the time!
- // It might be safe to just use rawurldecode instead, though.
- $m[1] = urldecode( ltrim( $m[1], ':' ) );
+ $m[1] = rawurldecode( ltrim( $m[1], ':' ) );
}
$title = Title::newFromText( $m[1] );
// If the title is a redirect to bad special pages or is invalid, return null
/**
* Get the main part with underscores
*
- * @return \type{\string} Main part of the title, with underscores
+ * @return String: Main part of the title, with underscores
*/
public function getDBkey() { return $this->mDbkeyform; }
/**
* Get the namespace index, i.e.\ one of the NS_xxxx constants.
*
- * @return \type{\int} Namespace index
+ * @return Integer: Namespace index
*/
public function getNamespace() { return $this->mNamespace; }
/**
* Get the namespace text
*
- * @return \type{\string} Namespace text
+ * @return String: Namespace text
*/
public function getNsText() {
global $wgContLang;
*/
public function getLocalURL( $query = '', $variant = false ) {
global $wgArticlePath, $wgScript, $wgServer, $wgRequest;
- global $wgVariantArticlePath, $wgContLang, $wgUser;
+ global $wgVariantArticlePath, $wgContLang;
if ( is_array( $query ) ) {
$query = wfArrayToCGI( $query );
}
- // internal links should point to same variant as current page (only anonymous users)
- if ( !$variant && $wgContLang->hasVariants() && !$wgUser->isLoggedIn() ) {
- $pref = $wgContLang->getPreferredVariant( false );
- if ( $pref != $wgContLang->getCode() ) {
- $variant = $pref;
- }
- }
-
if ( $this->isExternal() ) {
$url = $this->getFullURL();
if ( $query ) {
}
/**
- * Determines if $wgUser is unable to edit this page because it has been protected
+ * Determines if $user is unable to edit this page because it has been protected
* by $wgNamespaceProtection.
*
+ * @param $user User object, $wgUser will be used if not passed
* @return \type{\bool}
*/
- public function isNamespaceProtected() {
- global $wgNamespaceProtection, $wgUser;
+ public function isNamespaceProtected( User $user = null ) {
+ global $wgNamespaceProtection;
+
+ if ( $user === null ) {
+ global $wgUser;
+ $user = $wgUser;
+ }
+
if ( isset( $wgNamespaceProtection[$this->mNamespace] ) ) {
foreach ( (array)$wgNamespaceProtection[$this->mNamespace] as $right ) {
- if ( $right != '' && !$wgUser->isAllowed( $right ) ) {
+ if ( $right != '' && !$user->isAllowed( $right ) ) {
return true;
}
}
/**
* Check various permission hooks
- * @see checkQuickPermissions for parameter information
+ *
+ * @param $action String the action to check
+ * @param $user User user to check
+ * @param $errors Array list of current errors
+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
+ * @param $short Boolean short circuit on first error
+ *
+ * @return Array list of errors
*/
private function checkPermissionHooks( $action, $user, $errors, $doExpensiveQueries, $short ) {
// Use getUserPermissionsErrors instead
/**
* Check permissions on special pages & namespaces
- * @see checkQuickPermissions for parameter information
+ *
+ * @param $action String the action to check
+ * @param $user User user to check
+ * @param $errors Array list of current errors
+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
+ * @param $short Boolean short circuit on first error
+ *
+ * @return Array list of errors
*/
private function checkSpecialsAndNSPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
# Only 'createaccount' and 'execute' can be performed on
}
# Check $wgNamespaceProtection for restricted namespaces
- if ( $this->isNamespaceProtected() ) {
+ if ( $this->isNamespaceProtected( $user ) ) {
$ns = $this->mNamespace == NS_MAIN ?
wfMsg( 'nstab-main' ) : $this->getNsText();
$errors[] = $this->mNamespace == NS_MEDIAWIKI ?
/**
* Check CSS/JS sub-page permissions
- * @see checkQuickPermissions for parameter information
+ *
+ * @param $action String the action to check
+ * @param $user User user to check
+ * @param $errors Array list of current errors
+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
+ * @param $short Boolean short circuit on first error
+ *
+ * @return Array list of errors
*/
private function checkCSSandJSPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
# Protect css/js subpages of user pages
* Check against page_restrictions table requirements on this
* page. The user must possess all required rights for this
* action.
- * @see checkQuickPermissions for parameter information
+ *
+ * @param $action String the action to check
+ * @param $user User user to check
+ * @param $errors Array list of current errors
+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
+ * @param $short Boolean short circuit on first error
+ *
+ * @return Array list of errors
*/
private function checkPageRestrictions( $action, $user, $errors, $doExpensiveQueries, $short ) {
foreach ( $this->getRestrictions( $action ) as $right ) {
/**
* Check restrictions on cascading pages.
- * @see checkQuickPermissions for parameter information
+ *
+ * @param $action String the action to check
+ * @param $user User user to check
+ * @param $errors Array list of current errors
+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
+ * @param $short Boolean short circuit on first error
+ *
+ * @return Array list of errors
*/
private function checkCascadingSourcesRestrictions( $action, $user, $errors, $doExpensiveQueries, $short ) {
if ( $doExpensiveQueries && !$this->isCssJsSubpage() ) {
/**
* Check action permissions not already checked in checkQuickPermissions
- * @see checkQuickPermissions for parameter information
+ *
+ * @param $action String the action to check
+ * @param $user User user to check
+ * @param $errors Array list of current errors
+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
+ * @param $short Boolean short circuit on first error
+ *
+ * @return Array list of errors
*/
private function checkActionPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
if ( $action == 'protect' ) {
/**
* Check that the user isn't blocked from editting.
- * @see checkQuickPermissions for parameter information
+ *
+ * @param $action String the action to check
+ * @param $user User user to check
+ * @param $errors Array list of current errors
+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
+ * @param $short Boolean short circuit on first error
+ *
+ * @return Array list of errors
*/
private function checkUserBlock( $action, $user, $errors, $doExpensiveQueries, $short ) {
- if( $short ) {
+ if( $short && count( $errors ) > 0 ) {
return $errors;
}
return $this->mTitleProtection;
}
+ private function invalidateTitleProtectionCache() {
+ unset( $this->mTitleProtection );
+ }
+
/**
* Update the title protection status
*
$dbw->delete( 'protected_titles', array( 'pt_namespace' => $namespace,
'pt_title' => $title ), __METHOD__ );
}
+ $this->invalidateTitleProtectionCache();
+
# Update the protection log
if ( $dbw->affectedRows() ) {
$log = new LogPage( 'protect' );
array( 'pt_namespace' => $this->getNamespace(), 'pt_title' => $this->getDBkey() ),
__METHOD__
);
+ $this->invalidateTitleProtectionCache();
}
/**
/**
* Is this a *valid* .css or .js subpage of a user page?
- * Check that the corresponding skin exists
*
* @return \type{\bool}
+ * @deprecated
*/
public function isValidCssJsSubpage() {
- if ( $this->isCssJsSubpage() ) {
- $name = $this->getSkinFromCssJsSubpage();
- if ( $name == 'common' ) {
- return true;
- }
- $skinNames = Skin::getSkinNames();
- return array_key_exists( $name, $skinNames );
- } else {
- return false;
- }
+ return $this->isCssJsSubpage();
}
/**
}
if ( $purgeExpired ) {
Title::purgeExpiredRestrictions();
+ $this->invalidateTitleProtectionCache();
}
wfProfileOut( __METHOD__ );
if ( $purgeExpired ) {
Title::purgeExpiredRestrictions();
+ $this->invalidateTitleProtectionCache();
}
}
$this->mRestrictions['create'] = explode( ',', trim( $title_protection['pt_create_perm'] ) );
} else { // Get rid of the old restrictions
Title::purgeExpiredRestrictions();
+ $this->invalidateTitleProtectionCache();
}
} else {
$this->mRestrictionsExpiry['create'] = Block::decodeExpiry( '' );
* Uses link cache, adding it if necessary
*
* @param $flags \type{\int} a bit field; may be Title::GAID_FOR_UPDATE to select for update
- * @return \type{\bool}
+ * @return \type{\int}
*/
public function getLength( $flags = 0 ) {
if ( $this->mLength != -1 ) {
* This clears some fields in this object, and clears any associated
* keys in the "bad links" section of the link cache.
*
- * - This is called from Article::insertNewArticle() to allow
+ * - This is called from Article::doEdit() and Article::insertOn() to allow
* loading of the new page_id. It's also called from
* Article::doDeleteArticle()
*
$this->mInterwiki = $wgContLang->lc( $p );
# Redundant interwiki prefix to the local wiki
- if ( 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) ) {
+ if ( $wgLocalInterwiki !== false
+ && 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) )
+ {
if ( $dbkey == '' ) {
# Can't have an empty self-link
return false;
$retVal = array();
if ( $db->numRows( $res ) ) {
foreach ( $res as $row ) {
- if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
+ $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title );
+ if ( $titleObj ) {
$linkCache->addGoodLinkObj( $row->page_id, $titleObj, $row->page_len, $row->page_is_redirect, $row->page_latest );
$retVal[] = $titleObj;
}
# Truncate for whole multibyte characters. +5 bytes for ellipsis
$comment = $wgContLang->truncate( $comment, 250 );
- $newid = $nt->getArticleID();
$oldid = $this->getArticleID();
$latest = $this->getLatestRevId();
*/
public function countRevisionsBetween( $old, $new ) {
$dbr = wfGetDB( DB_SLAVE );
- return (int)$dbr->selectField( 'revision', 'count(*)',
- 'rev_page = ' . intval( $this->getArticleId() ) .
- ' AND rev_id > ' . intval( $old ) .
- ' AND rev_id < ' . intval( $new ),
- __METHOD__
+ return (int)$dbr->selectField( 'revision', 'count(*)', array(
+ 'rev_page' => intval( $this->getArticleId() ),
+ 'rev_id > ' . intval( $old ),
+ 'rev_id < ' . intval( $new )
+ ), __METHOD__
);
}
+ /**
+ * Get the number of authors between the given revision IDs.
+ * Used for diffs and other things that really need it.
+ *
+ * @param $fromRevId \type{\int} Revision ID (first before range)
+ * @param $toRevId \type{\int} Revision ID (first after range)
+ * @param $limit \type{\int} Maximum number of authors
+ * @param $flags \type{\int} Title::GAID_FOR_UPDATE
+ * @return \type{\int}
+ */
+ public function countAuthorsBetween( $fromRevId, $toRevId, $limit, $flags = 0 ) {
+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+ $res = $db->select( 'revision', 'DISTINCT rev_user_text',
+ array(
+ 'rev_page' => $this->getArticleID(),
+ 'rev_id > ' . (int)$fromRevId,
+ 'rev_id < ' . (int)$toRevId
+ ), __METHOD__,
+ array( 'LIMIT' => $limit )
+ );
+ return (int)$db->numRows( $res );
+ }
+
/**
* Compare with another title.
*
* In other words, is this a content page, for the purposes of calculating
* statistics, etc?
*
- * @return \type{\bool}
+ * @return Boolean
*/
public function isContentPage() {
return MWNamespace::isContent( $this->getNamespace() );