MediaWiki REL1_39
SpecialPageLanguage.php
Go to the documentation of this file.
1<?php
32
42 private $goToUrl;
43
45 private $contentHandlerFactory;
46
48 private $languageNameUtils;
49
51 private $loadBalancer;
52
54 private $searchEngineFactory;
55
62 public function __construct(
63 IContentHandlerFactory $contentHandlerFactory,
64 LanguageNameUtils $languageNameUtils,
65 ILoadBalancer $loadBalancer,
66 SearchEngineFactory $searchEngineFactory
67 ) {
68 parent::__construct( 'PageLanguage', 'pagelang' );
69 $this->contentHandlerFactory = $contentHandlerFactory;
70 $this->languageNameUtils = $languageNameUtils;
71 $this->loadBalancer = $loadBalancer;
72 $this->searchEngineFactory = $searchEngineFactory;
73 }
74
75 public function doesWrites() {
76 return true;
77 }
78
79 protected function preHtml() {
80 $this->getOutput()->addModules( 'mediawiki.misc-authed-ooui' );
81 return parent::preHtml();
82 }
83
84 protected function getFormFields() {
85 // Get default from the subpage of Special page
86 $defaultName = $this->par;
87 $title = $defaultName ? Title::newFromText( $defaultName ) : null;
88 if ( $title ) {
89 $defaultPageLanguage = $this->contentHandlerFactory->getContentHandler( $title->getContentModel() )
90 ->getPageLanguage( $title );
91
92 $hasCustomLanguageSet = !$defaultPageLanguage->equals( $title->getPageLanguage() );
93 } else {
94 $hasCustomLanguageSet = false;
95 }
96
97 $page = [];
98 $page['pagename'] = [
99 'type' => 'title',
100 'label-message' => 'pagelang-name',
101 'default' => $title ? $title->getPrefixedText() : $defaultName,
102 'autofocus' => $defaultName === null,
103 'exists' => true,
104 ];
105
106 // Options for whether to use the default language or select language
107 $selectoptions = [
108 (string)$this->msg( 'pagelang-use-default' )->escaped() => 1,
109 (string)$this->msg( 'pagelang-select-lang' )->escaped() => 2,
110 ];
111 $page['selectoptions'] = [
112 'id' => 'mw-pl-options',
113 'type' => 'radio',
114 'options' => $selectoptions,
115 'default' => $hasCustomLanguageSet ? 2 : 1
116 ];
117
118 // Building a language selector
119 $userLang = $this->getLanguage()->getCode();
120 $languages = $this->languageNameUtils->getLanguageNames( $userLang, LanguageNameUtils::SUPPORTED );
121 $options = [];
122 foreach ( $languages as $code => $name ) {
123 $options["$code - $name"] = $code;
124 }
125
126 $page['language'] = [
127 'id' => 'mw-pl-languageselector',
128 'cssclass' => 'mw-languageselector',
129 'type' => 'select',
130 'options' => $options,
131 'label-message' => 'pagelang-language',
132 'default' => $title ?
133 $title->getPageLanguage()->getCode() :
134 $this->getConfig()->get( MainConfigNames::LanguageCode ),
135 ];
136
137 // Allow user to enter a comment explaining the change
138 $page['reason'] = [
139 'type' => 'text',
140 'label-message' => 'pagelang-reason'
141 ];
142
143 return $page;
144 }
145
146 protected function postHtml() {
147 if ( $this->par ) {
148 return $this->showLogFragment( $this->par );
149 }
150 return '';
151 }
152
153 protected function getDisplayFormat() {
154 return 'ooui';
155 }
156
157 public function alterForm( HTMLForm $form ) {
158 $this->getHookRunner()->onLanguageSelector( $this->getOutput(), 'mw-languageselector' );
159 $form->setSubmitTextMsg( 'pagelang-submit' );
160 }
161
166 public function onSubmit( array $data ) {
167 $pageName = $data['pagename'];
168
169 // Check if user wants to use default language
170 if ( $data['selectoptions'] == 1 ) {
171 $newLanguage = 'default';
172 } else {
173 $newLanguage = $data['language'];
174 }
175
176 try {
177 $title = Title::newFromTextThrow( $pageName );
178 } catch ( MalformedTitleException $ex ) {
179 return Status::newFatal( $ex->getMessageObject() );
180 }
181
182 // Check permissions and make sure the user has permission to edit the page
183 $status = PermissionStatus::newEmpty();
184 if ( !$this->getAuthority()->authorizeWrite( 'edit', $title, $status ) ) {
185 $wikitext = $this->getOutput()->formatPermissionStatus( $status );
186 // Hack to get our wikitext parsed
187 return Status::newFatal( new RawMessage( '$1', [ $wikitext ] ) );
188 }
189
190 // Url to redirect to after the operation
191 $this->goToUrl = $title->getFullUrlForRedirect(
192 $title->isRedirect() ? [ 'redirect' => 'no' ] : []
193 );
194
196 $this->getContext(),
197 $title,
198 $newLanguage,
199 $data['reason'] ?? '',
200 [],
201 $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_PRIMARY )
202 );
203 }
204
216 public static function changePageLanguage( IContextSource $context, Title $title,
217 $newLanguage, $reason = "", array $tags = [], IDatabase $dbw = null ) {
218 // Get the default language for the wiki
219 $defLang = $context->getConfig()->get( MainConfigNames::LanguageCode );
220
221 $pageId = $title->getArticleID();
222
223 // Check if article exists
224 if ( !$pageId ) {
225 return Status::newFatal(
226 'pagelang-nonexistent-page',
227 wfEscapeWikiText( $title->getPrefixedText() )
228 );
229 }
230
231 // Load the page language from DB
232 $dbw = $dbw ?? wfGetDB( DB_PRIMARY );
233 $oldLanguage = $dbw->selectField(
234 'page',
235 'page_lang',
236 [ 'page_id' => $pageId ],
237 __METHOD__
238 );
239
240 // Check if user wants to use the default language
241 if ( $newLanguage === 'default' ) {
242 $newLanguage = null;
243 }
244
245 // No change in language
246 if ( $newLanguage === $oldLanguage ) {
247 // Check if old language does not exist
248 if ( !$oldLanguage ) {
249 return Status::newFatal( ApiMessage::create(
250 [
251 'pagelang-unchanged-language-default',
252 wfEscapeWikiText( $title->getPrefixedText() )
253 ],
254 'pagelang-unchanged-language'
255 ) );
256 }
257 return Status::newFatal(
258 'pagelang-unchanged-language',
259 wfEscapeWikiText( $title->getPrefixedText() ),
260 $oldLanguage
261 );
262 }
263
264 // Hardcoded [def] if the language is set to null
265 $logOld = $oldLanguage ?: $defLang . '[def]';
266 $logNew = $newLanguage ?: $defLang . '[def]';
267
268 // Writing new page language to database
269 $dbw->update(
270 'page',
271 [ 'page_lang' => $newLanguage ],
272 [
273 'page_id' => $pageId,
274 'page_lang' => $oldLanguage
275 ],
276 __METHOD__
277 );
278
279 if ( !$dbw->affectedRows() ) {
280 return Status::newFatal( 'pagelang-db-failed' );
281 }
282
283 // Logging change of language
284 $logParams = [
285 '4::oldlanguage' => $logOld,
286 '5::newlanguage' => $logNew
287 ];
288 $entry = new ManualLogEntry( 'pagelang', 'pagelang' );
289 $entry->setPerformer( $context->getUser() );
290 $entry->setTarget( $title );
291 $entry->setParameters( $logParams );
292 $entry->setComment( is_string( $reason ) ? $reason : "" );
293 $entry->addTags( $tags );
294
295 $logid = $entry->insert();
296 $entry->publish( $logid );
297
298 // Force re-render so that language-based content (parser functions etc.) gets updated
299 $title->invalidateCache();
300
301 return Status::newGood( (object)[
302 'oldLanguage' => $logOld,
303 'newLanguage' => $logNew,
304 'logId' => $logid,
305 ] );
306 }
307
308 public function onSuccess() {
309 // Success causes a redirect
310 $this->getOutput()->redirect( $this->goToUrl );
311 }
312
313 private function showLogFragment( $title ) {
314 $moveLogPage = new LogPage( 'pagelang' );
315 $out1 = Xml::element( 'h2', null, $moveLogPage->getName()->text() );
316 $out2 = '';
317 LogEventsList::showLogExtract( $out2, 'pagelang', $title );
318 return $out1 . $out2;
319 }
320
329 public function prefixSearchSubpages( $search, $limit, $offset ) {
330 return $this->prefixSearchString( $search, $limit, $offset, $this->searchEngineFactory );
331 }
332
333 protected function getGroupName() {
334 return 'pagetools';
335 }
336}
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Special page which uses an HTMLForm to handle processing.
string null $par
The sub-page of the special page.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:150
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Class to simplify the use of log pages.
Definition LogPage.php:39
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
Class for creating new log entries and inserting them into the database.
A service that provides utilities to do with language names and codes.
A class containing constants representing the names of configuration variables.
A StatusValue for permission errors.
Variant of the Message class.
Factory class for SearchEngine.
Special page for changing the content language of a page.
getFormFields()
Get an HTMLForm descriptor array.
postHtml()
Add post-HTML to the form.
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
__construct(IContentHandlerFactory $contentHandlerFactory, LanguageNameUtils $languageNameUtils, ILoadBalancer $loadBalancer, SearchEngineFactory $searchEngineFactory)
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
static changePageLanguage(IContextSource $context, Title $title, $newLanguage, $reason="", array $tags=[], IDatabase $dbw=null)
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
preHtml()
Add pre-HTML to the form.
doesWrites()
Indicates whether this special page may perform database writes.
getDisplayFormat()
Get display format for the form.
getOutput()
Get the OutputPage being used for this instance.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getAuthority()
Shortcut to get the Authority executing this instance.
getConfig()
Shortcut to get main config object.
prefixSearchString( $search, $limit, $offset, SearchEngineFactory $searchEngineFactory=null)
Perform a regular substring search for prefixSearchSubpages.
getLanguage()
Shortcut to get user's language.
Represents a title within MediaWiki.
Definition Title.php:49
Interface for objects which can provide a MediaWiki context on request.
getConfig()
Get the site configuration.
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:39
Create and track the database connections and transactions for a given database cluster.
const DB_PRIMARY
Definition defines.php:28