wiki.techinc.nl/includes/specials/SpecialMyLanguage.php
Florian 29cac40c82 SpecialMyLanguage: Use page language instead of wiki language for redirect target check
With the change, named in Follow up, it's possible for site owners to
allow to change the language of a page using a special page.
Theoretically, any page can have another or a different page language,
depending on, if the language was changed using the special page or not.
For Special:MyLanguage it isn't enough anymore to check, if the current
user language is the same as the default content language. It has to
check, if the page language (which can potentionally differ from the
default content language) is the same as the user language.

The problem:
If content language is the same as the user language, Special:MyLanguage
currently redirects to the "base page" of a page ("Testpage" instead of
"Testpage/de"), no matter, if the page language of the base part is
another one as the default content language. This can result in the
problem, that Special:MyLanguage redirects to a page, that has a
different language as the user language, even if a subpage with the user
language code exists. This is fixed with this change.

Follow up: I0f82b146fbe948f917c1

Bug: T121834
Change-Id: Ic9fc9049813c153111829d37a2c248dc0768e0fb
2016-08-23 12:57:37 +00:00

113 lines
3.1 KiB
PHP

<?php
/**
* Implements Special:MyLanguage
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @author Niklas Laxström
* @author Siebrand Mazeland
* @copyright Copyright © 2010-2013 Niklas Laxström, Siebrand Mazeland
*/
/**
* Unlisted special page just to redirect the user to the translated version of
* a page, if it exists.
*
* Usage: [[Special:MyLanguage/Page name|link text]]
*
* @since 1.24
* @ingroup SpecialPage
*/
class SpecialMyLanguage extends RedirectSpecialArticle {
public function __construct() {
parent::__construct( 'MyLanguage' );
}
/**
* If the special page is a redirect, then get the Title object it redirects to.
* False otherwise.
*
* @param string|null $subpage
* @return Title
*/
public function getRedirect( $subpage ) {
$title = $this->findTitle( $subpage );
// Go to the main page if given invalid title.
if ( !$title ) {
$title = Title::newMainPage();
}
return $title;
}
/**
* Assuming the user's interface language is fi. Given input Page, it
* returns Page/fi if it exists, otherwise Page. Given input Page/de,
* it returns Page/fi if it exists, otherwise Page/de if it exists,
* otherwise Page.
*
* @param string|null $subpage
* @return Title|null
*/
public function findTitle( $subpage ) {
// base = title without language code suffix
// provided = the title as it was given
$base = $provided = null;
if ( $subpage !== null ) {
$provided = Title::newFromText( $subpage );
$base = $provided;
}
if ( $provided && strpos( $subpage, '/' ) !== false ) {
$pos = strrpos( $subpage, '/' );
$basepage = substr( $subpage, 0, $pos );
$code = substr( $subpage, $pos + 1 );
if ( strlen( $code ) && Language::isKnownLanguageTag( $code ) ) {
$base = Title::newFromText( $basepage );
}
}
if ( !$base ) {
return null;
}
if ( $base->isRedirect() ) {
$page = new WikiPage( $base );
$base = $page->getRedirectTarget();
}
$uiCode = $this->getLanguage()->getCode();
$proposed = $base->getSubpage( $uiCode );
if ( $proposed && $proposed->exists() && $uiCode !== $base->getPageLanguage()->getCode() ) {
return $proposed;
} elseif ( $provided && $provided->exists() ) {
return $provided;
} else {
return $base;
}
}
/**
* Target can identify a specific user's language preference.
*
* @see T109724
* @since 1.27
* @return bool
*/
public function personallyIdentifiableTarget() {
return true;
}
}