/** @var string Interwiki prefix */
public $mInterwiki = '';
+ /** @var bool Was this Title created from a string with a local interwiki prefix? */
+ private $mLocalInterwiki = false;
+
/** @var string Title fragment (i.e. the bit after the #) */
public $mFragment = '';
/** @var array Array of groups allowed to edit this article */
public $mRestrictions = array();
- /** @var bool */
+ /** @var bool */
protected $mOldRestrictions = false;
/** @var bool Cascade restrictions on this page to included templates and images? */
* Note that this doesn't pick up many things that could be wrong with titles, but that
* replacing this regex with something valid will make many titles valid.
*
- * @todo: move this into MediaWikiTitleCodec
+ * @todo move this into MediaWikiTitleCodec
*
* @return string Regex string
*/
return $this->mInterwiki;
}
+ /**
+ * Was this a local interwiki link?
+ *
+ * @return bool
+ */
+ public function wasLocalInterwiki() {
+ return $this->mLocalInterwiki;
+ }
+
/**
* Determine whether the object refers to a page within
* this project and is transcludable.
/**
* Get a TitleValue object representing this Title.
*
- * @note: Not all valid Titles have a corresponding valid TitleValue
+ * @note Not all valid Titles have a corresponding valid TitleValue
* (e.g. TitleValues cannot represent page-local links that have a
* fragment but no title text).
*
/**
* Returns true if the title is inside one of the specified namespaces.
*
- * @param ...$namespaces The namespaces to check for
+ * @param int $namespaces,... The namespaces to check for
* @return bool
* @since 1.19
*/
* $wgServer is prepended to make an absolute URL.
*
* @see self::getFullURL to always get an absolute URL.
+ * @see self::getLinkURL to always get a URL that's the simplest URL that will be
+ * valid to link, locally, to the current Title.
* @see self::newFromText to produce a Title object.
*
- * @param string|array $query an optional query string,
+ * @param string|array $query An optional query string,
* not used for interwiki links. Can be specified as an associative array as well,
* e.g., array( 'action' => 'edit' ) (keys and values will be URL-escaped).
* Some query patterns will trigger various shorturl path replacements.
*
* @todo FIXME: This *does not* check throttles (User::pingLimiter()).
*
- * @param string $action action that permission needs to be checked for
+ * @param string $action Action that permission needs to be checked for
* @param User $user User to check
* @param bool $doExpensiveQueries Set this to false to avoid doing unnecessary
* queries by skipping checks for cascading protections and user blocks.
- * @param array $ignoreErrors of Strings Set this to a list of message keys
+ * @param array $ignoreErrors Array of Strings Set this to a list of message keys
* whose corresponding errors may be ignored.
* @return array Array of arguments to wfMessage to explain permissions problems.
*/
/**
* Permissions checks that fail most often, and which are easiest to test.
*
- * @param string $action the action to check
+ * @param string $action The action to check
* @param User $user User to check
* @param array $errors List of current errors
* @param bool $doExpensiveQueries Whether or not to perform expensive queries
$ns = $this->mNamespace == NS_MAIN ?
wfMessage( 'nstab-main' )->text() : $this->getNsText();
$errors[] = $this->mNamespace == NS_MEDIAWIKI ?
- array( 'protectedinterface' ) : array( 'namespaceprotected', $ns );
+ array( 'protectedinterface', $action ) : array( 'namespaceprotected', $ns, $action );
}
return $errors;
if ( $action != 'patrol' && !$user->isAllowed( 'editusercssjs' ) ) {
if ( preg_match( '/^' . preg_quote( $user->getName(), '/' ) . '\//', $this->mTextform ) ) {
if ( $this->isCssSubpage() && !$user->isAllowedAny( 'editmyusercss', 'editusercss' ) ) {
- $errors[] = array( 'mycustomcssprotected' );
+ $errors[] = array( 'mycustomcssprotected', $action );
} elseif ( $this->isJsSubpage() && !$user->isAllowedAny( 'editmyuserjs', 'edituserjs' ) ) {
- $errors[] = array( 'mycustomjsprotected' );
+ $errors[] = array( 'mycustomjsprotected', $action );
}
} else {
if ( $this->isCssSubpage() && !$user->isAllowed( 'editusercss' ) ) {
- $errors[] = array( 'customcssprotected' );
+ $errors[] = array( 'customcssprotected', $action );
} elseif ( $this->isJsSubpage() && !$user->isAllowed( 'edituserjs' ) ) {
- $errors[] = array( 'customjsprotected' );
+ $errors[] = array( 'customjsprotected', $action );
}
}
}
continue;
}
if ( !$user->isAllowed( $right ) ) {
- $errors[] = array( 'protectedpagetext', $right );
+ $errors[] = array( 'protectedpagetext', $right, $action );
} elseif ( $this->mCascadeRestriction && !$user->isAllowed( 'protect' ) ) {
- $errors[] = array( 'protectedpagetext', 'protect' );
+ $errors[] = array( 'protectedpagetext', 'protect', $action );
}
}
foreach ( $cascadingSources as $page ) {
$pages .= '* [[:' . $page->getPrefixedText() . "]]\n";
}
- $errors[] = array( 'cascadeprotected', count( $cascadingSources ), $pages );
+ $errors[] = array( 'cascadeprotected', count( $cascadingSources ), $pages, $action );
}
}
}
$errors[] = array( 'immobile-target-page' );
}
} elseif ( $action == 'delete' ) {
+ if ( count( $this->getUserPermissionsErrorsInternal( 'edit',
+ $user, $doExpensiveQueries, true ) )
+ ) {
+ // If they can't edit, they shouldn't delete.
+ $errors[] = array( 'delete-cantedit' );
+ }
if ( $doExpensiveQueries && $wgDeleteRevisionsLimit
&& !$this->userCan( 'bigdelete', $user ) && $this->isBigDeletion()
) {
'checkPermissionHooks',
'checkReadPermissions',
);
+ # Don't call checkSpecialsAndNSPermissions or checkCSSandJSPermissions
+ # here as it will lead to duplicate error messages. This is okay to do
+ # since anywhere that checks for create will also check for edit, and
+ # those checks are called for edit.
+ } elseif ( $action == 'create' ) {
+ $checks = array(
+ 'checkQuickPermissions',
+ 'checkPermissionHooks',
+ 'checkPageRestrictions',
+ 'checkCascadingSourcesRestrictions',
+ 'checkActionPermissions',
+ 'checkUserBlock'
+ );
} else {
$checks = array(
'checkQuickPermissions',
/**
* Does the title correspond to a protected article?
*
- * @param string $action the action the page is protected from,
+ * @param string $action The action the page is protected from,
* by default checks all actions.
* @return bool
*/
# Fill fields
$this->setFragment( '#' . $parts['fragment'] );
$this->mInterwiki = $parts['interwiki'];
+ $this->mLocalInterwiki = $parts['local_interwiki'];
$this->mNamespace = $parts['namespace'];
$this->mUserCaseDBKey = $parts['user_case_dbkey'];
$log->addRelations( 'pr_id', $logRelationsValues, $logId );
}
+ // Update *_from_namespace fields as needed
+ if ( $this->getNamespace() != $nt->getNamespace() ) {
+ $dbw->update( 'pagelinks',
+ array( 'pl_from_namespace' => $nt->getNamespace() ),
+ array( 'pl_from' => $pageid ),
+ __METHOD__
+ );
+ $dbw->update( 'templatelinks',
+ array( 'tl_from_namespace' => $nt->getNamespace() ),
+ array( 'tl_from' => $pageid ),
+ __METHOD__
+ );
+ $dbw->update( 'imagelinks',
+ array( 'il_from_namespace' => $nt->getNamespace() ),
+ array( 'il_from' => $pageid ),
+ __METHOD__
+ );
+ }
+
# Update watchlists
- $oldnamespace = MWNamespace::getSubject( $this->getNamespace() );
- $newnamespace = MWNamespace::getSubject( $nt->getNamespace() );
$oldtitle = $this->getDBkey();
$newtitle = $nt->getDBkey();
-
- if ( $oldnamespace != $newnamespace || $oldtitle != $newtitle ) {
+ $oldsnamespace = MWNamespace::getSubject( $this->getNamespace() );
+ $newsnamespace = MWNamespace::getSubject( $nt->getNamespace() );
+ if ( $oldsnamespace != $newsnamespace || $oldtitle != $newtitle ) {
WatchedItem::duplicateEntries( $this, $nt );
}