You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

311 lines
8.5 KiB
PHP

<?php
namespace LatinizeUrl;
use UnlistedSpecialPage;
use Html;
use MediaWiki\MediaWikiServices;
use MediaWiki\Session\CsrfTokenSet;
use ThrottledError;
class SpecialCustomUrl extends UnlistedSpecialPage {
/**
* @var string
*/
protected $target;
/**
* @var \Title
*/
protected $title;
/** @var string */
protected $slug;
/** @var bool */
protected $isAdmin;
/** @var bool */
protected $userEditedPage;
/** @var NamespaceInfo */
private $nsInfo;
/** @var LinkBatchFactory */
private $linkBatchFactory;
public function __construct() {
parent::__construct('CustomUrl', '', false);
$service = MediaWikiServices::getInstance();
$this->nsInfo = $service->getNamespaceInfo();
$this->linkBatchFactory = $service->getLinkBatchFactory();
}
public function doesWrites() {
return true;
}
public function execute($par) {
$this->useTransactionalTimeLimit();
$this->checkReadOnly();
$this->setHeaders();
$this->outputHeader();
$service = MediaWikiServices::getInstance();
$request = $this->getRequest();
$this->target = $par ?? $request->getText('target');
$title = \Title::newFromText($this->target);
$this->title = $title;
$this->getSkin()->setRelevantTitle($this->title);
$user = $this->getUser();
if (!$title) {
throw new \ErrorPageError( 'notargettitle', 'notargettext' );
return;
}
if (!$title->exists()) {
throw new \ErrorPageError( 'nopagetitle', 'nopagetext' );
}
$isAdmin = $service->getPermissionManager()->userHasRight($this->getUser(), 'move');
$this->isAdmin = $isAdmin;
$userEditedPage = Utils::hasUserEditedPage($this->title, $this->getUser());
$this->userEditedPage = $userEditedPage;
if (!$this->hasAccess()){
throw new \PermissionsError('move');
}
$this->slug = $this->getCurrentSlug();
if ($request->getRawVal('action') == 'submit' && $request->wasPosted() && $user->matchEditToken($request->getVal('wpEditToken'))) {
$this->doSubmit();
} else {
$this->showForm( [] );
}
}
protected function hasAccess(){
return $this->isAdmin || $this->userEditedPage;
}
protected function showForm($err, $isPermError = false){
$user = $this->getUser();
$out = $this->getOutput();
$out->setPageTitle($this->msg('latinizeurl-customurl'));
$out->addModuleStyles([
'mediawiki.special',
'mediawiki.interface.helpers.styles'
]);
$out->addModules('mediawiki.misc-authed-ooui');
$out->enableOOUI();
$fields = [];
$fields[] = new \OOUI\FieldLayout(
new \OOUI\TextInputWidget([
'name' => 'wpSlug',
'id' => 'wpSlug',
'value' => $this->getCurrentSlug(),
]),
[
'label' => $this->msg('customurl-url-field-label')->text(),
'help' => $this->msg('customurl-url-field-help')->text(),
'align' => 'top',
]
);
if ($this->title->hasSubpages()) {
$fields[] = new \OOUI\FieldLayout(
new \OOUI\CheckboxInputWidget([
'name' => 'wpRenameSubpage',
'id' => 'wpRenameSubpage',
'value' => '1',
]),
[
'label' => $this->msg('rename-subpage-checkbox-label')->text(),
'align' => 'inline',
]
);
}
$fields[] = new \OOUI\FieldLayout(
new \OOUI\ButtonInputWidget( [
'name' => 'wpConfirm',
'value' => $this->msg('htmlform-submit')->text(),
'label' => $this->msg('htmlform-submit')->text(),
'flags' => ['primary', 'progressive'],
'type' => 'submit',
]),
[
'align' => 'top',
]
);
$fieldset = new \OOUI\FieldsetLayout( [
'label' => $this->msg('customurl-legend')->text(),
'id' => 'mw-customurl-table',
'items' => $fields,
] );
$form = new \OOUI\FormLayout([
'method' => 'post',
'action' => $this->getPageTitle($this->target)->getLocalURL('action=submit'),
'id' => 'customurl',
]);
$form->appendContent(
$fieldset,
new \OOUI\HtmlSnippet(
Html::hidden('wpEditToken', $user->getEditToken())
)
);
$out->addHTML(
new \OOUI\PanelLayout([
'classes' => ['movepage-wrapper', 'customurl-wrapper'],
'expanded' => false,
'padded' => true,
'framed' => true,
'content' => $form,
])
);
if ($this->title->hasSubpages()) {
$this->showSubpages($this->title);
}
}
private function getCurrentSlug(){
$slug = Utils::getSlugUrlByTitle($this->title);
if($slug){
return $slug;
} else {
return $this->title->getText();
}
}
public function doSubmit() {
$user = $this->getUser();
if ($user->pingLimiter('customurl')) {
throw new ThrottledError;
}
$request = $this->getRequest();
$slug = $request->getText('wpSlug');
$renameSubpages = $request->getBool('wpRenameSubpage');
$originSlug = Utils::getSlugByTitle($this->title);
$latinize = [];
if (empty($slug)) { //自动生成
$parsedData = Utils::parseTitleToAscii($this->title, $this->title->getPageLanguage());
$slug = $parsedData['slug'];
$latinize = $parsedData['latinize'];
$custom = 0;
} else {
$slug = str_replace('_', ' ', $slug);
$latinize = [$slug];
$custom = 1;
}
if(Utils::titleSlugExists($this->title)){
$realSlug = Utils::updateTitleSlugMap($this->title->getText(), $slug, $latinize, $custom);
} else {
$realSlug = Utils::addTitleSlugMap($this->title->getText(), $slug, $latinize, $custom);
}
if($renameSubpages){
//更新子页面的slug
$subpages = $this->title->getSubpages();
$originSlugLen = strlen($originSlug);
/** @var \Title $subpage */
foreach($subpages as $subpage){
$originSubpaeSlug = Utils::getSlugByTitle($subpage);
if(strpos($originSubpaeSlug, $originSlug) === 0){
$newSubpageSlug = $realSlug . substr($originSubpaeSlug, $originSlugLen);
Utils::updateTitleSlugMap($subpage->getText(), $newSubpageSlug, [$newSubpageSlug], 1);
}
}
}
$this->slug = $realSlug;
$this->onSuccess();
return true;
}
/**
* Show subpages of the page being moved. Section is not shown if both current
* namespace does not support subpages and no talk subpages were found.
*
* @param Title $title Page being moved.
*/
private function showSubpages( $title ) {
$nsHasSubpages = $this->nsInfo->hasSubpages( $title->getNamespace() );
$subpages = $title->getSubpages();
$count = $subpages instanceof \TitleArray ? $subpages->count() : 0;
$titleIsTalk = $title->isTalkPage();
$subpagesTalk = $title->getTalkPage()->getSubpages();
$countTalk = $subpagesTalk instanceof \TitleArray ? $subpagesTalk->count() : 0;
$totalCount = $count + $countTalk;
if ( !$nsHasSubpages && $countTalk == 0 ) {
return;
}
$this->getOutput()->wrapWikiMsg(
'== $1 ==',
[ 'movesubpage', ( $titleIsTalk ? $count : $totalCount ) ]
);
if ( $nsHasSubpages ) {
$this->showSubpagesList( $subpages, $count, 'movesubpagetext', true );
}
if ( !$titleIsTalk && $countTalk > 0 ) {
$this->showSubpagesList( $subpagesTalk, $countTalk, 'movesubpagetalktext' );
}
}
private function showSubpagesList( $subpages, $pagecount, $wikiMsg, $noSubpageMsg = false ) {
$out = $this->getOutput();
# No subpages.
if ( $pagecount == 0 && $noSubpageMsg ) {
$out->addWikiMsg( 'movenosubpage' );
return;
}
$out->addWikiMsg( $wikiMsg, $this->getLanguage()->formatNum( $pagecount ) );
$out->addHTML( "<ul>\n" );
$linkBatch = $this->linkBatchFactory->newLinkBatch( $subpages );
$linkBatch->setCaller( __METHOD__ );
$linkBatch->execute();
$linkRenderer = $this->getLinkRenderer();
foreach ( $subpages as $subpage ) {
$link = $linkRenderer->makeLink( $subpage );
$out->addHTML( "<li>$link</li>\n" );
}
$out->addHTML( "</ul>\n" );
}
public function onSuccess(){
$out = $this->getOutput();
$out->setPageTitle($this->msg('latinizeurl-customurl'));
$out->addWikiMsg('customurl-set-success', $this->title->getText(), str_replace(' ', '_', $this->slug));
}
protected function getGroupName() {
return 'pagetools';
}
}