MediaWiki 1.40.4
SpecialPageLanguage.php
Go to the documentation of this file.
1<?php
34
44 private $goToUrl;
45
47 private $contentHandlerFactory;
48
50 private $languageNameUtils;
51
53 private $loadBalancer;
54
56 private $searchEngineFactory;
57
64 public function __construct(
65 IContentHandlerFactory $contentHandlerFactory,
66 LanguageNameUtils $languageNameUtils,
67 ILoadBalancer $loadBalancer,
68 SearchEngineFactory $searchEngineFactory
69 ) {
70 parent::__construct( 'PageLanguage', 'pagelang' );
71 $this->contentHandlerFactory = $contentHandlerFactory;
72 $this->languageNameUtils = $languageNameUtils;
73 $this->loadBalancer = $loadBalancer;
74 $this->searchEngineFactory = $searchEngineFactory;
75 }
76
77 public function doesWrites() {
78 return true;
79 }
80
81 protected function preHtml() {
82 $this->getOutput()->addModules( 'mediawiki.misc-authed-ooui' );
83 return parent::preHtml();
84 }
85
86 protected function getFormFields() {
87 // Get default from the subpage of Special page
88 $defaultName = $this->par;
89 $title = $defaultName ? Title::newFromText( $defaultName ) : null;
90 if ( $title ) {
91 $defaultPageLanguage = $this->contentHandlerFactory->getContentHandler( $title->getContentModel() )
92 ->getPageLanguage( $title );
93
94 $hasCustomLanguageSet = !$defaultPageLanguage->equals( $title->getPageLanguage() );
95 } else {
96 $hasCustomLanguageSet = false;
97 }
98
99 $page = [];
100 $page['pagename'] = [
101 'type' => 'title',
102 'label-message' => 'pagelang-name',
103 'default' => $title ? $title->getPrefixedText() : $defaultName,
104 'autofocus' => $defaultName === null,
105 'exists' => true,
106 ];
107
108 // Options for whether to use the default language or select language
109 $selectoptions = [
110 (string)$this->msg( 'pagelang-use-default' )->escaped() => 1,
111 (string)$this->msg( 'pagelang-select-lang' )->escaped() => 2,
112 ];
113 $page['selectoptions'] = [
114 'id' => 'mw-pl-options',
115 'type' => 'radio',
116 'options' => $selectoptions,
117 'default' => $hasCustomLanguageSet ? 2 : 1
118 ];
119
120 // Building a language selector
121 $userLang = $this->getLanguage()->getCode();
122 $languages = $this->languageNameUtils->getLanguageNames( $userLang, LanguageNameUtils::SUPPORTED );
123 $options = [];
124 foreach ( $languages as $code => $name ) {
125 $options["$code - $name"] = $code;
126 }
127
128 $page['language'] = [
129 'id' => 'mw-pl-languageselector',
130 'cssclass' => 'mw-languageselector',
131 'type' => 'select',
132 'options' => $options,
133 'label-message' => 'pagelang-language',
134 'default' => $title ?
135 $title->getPageLanguage()->getCode() :
136 $this->getConfig()->get( MainConfigNames::LanguageCode ),
137 ];
138
139 // Allow user to enter a comment explaining the change
140 $page['reason'] = [
141 'type' => 'text',
142 'label-message' => 'pagelang-reason'
143 ];
144
145 return $page;
146 }
147
148 protected function postHtml() {
149 if ( $this->par ) {
150 return $this->showLogFragment( $this->par );
151 }
152 return '';
153 }
154
155 protected function getDisplayFormat() {
156 return 'ooui';
157 }
158
159 public function alterForm( HTMLForm $form ) {
160 $this->getHookRunner()->onLanguageSelector( $this->getOutput(), 'mw-languageselector' );
161 $form->setSubmitTextMsg( 'pagelang-submit' );
162 }
163
168 public function onSubmit( array $data ) {
169 $pageName = $data['pagename'];
170
171 // Check if user wants to use default language
172 if ( $data['selectoptions'] == 1 ) {
173 $newLanguage = 'default';
174 } else {
175 $newLanguage = $data['language'];
176 }
177
178 try {
179 $title = Title::newFromTextThrow( $pageName );
180 } catch ( MalformedTitleException $ex ) {
181 return Status::newFatal( $ex->getMessageObject() );
182 }
183
184 // Check permissions and make sure the user has permission to edit the page
185 $status = PermissionStatus::newEmpty();
186 if ( !$this->getAuthority()->authorizeWrite( 'edit', $title, $status ) ) {
187 $wikitext = $this->getOutput()->formatPermissionStatus( $status );
188 // Hack to get our wikitext parsed
189 return Status::newFatal( new RawMessage( '$1', [ $wikitext ] ) );
190 }
191
192 // Url to redirect to after the operation
193 $this->goToUrl = $title->getFullUrlForRedirect(
194 $title->isRedirect() ? [ 'redirect' => 'no' ] : []
195 );
196
198 $this->getContext(),
199 $title,
200 $newLanguage,
201 $data['reason'] ?? '',
202 [],
203 $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_PRIMARY )
204 );
205 }
206
218 public static function changePageLanguage( IContextSource $context, Title $title,
219 $newLanguage, $reason = "", array $tags = [], IDatabase $dbw = null ) {
220 // Get the default language for the wiki
221 $defLang = $context->getConfig()->get( MainConfigNames::LanguageCode );
222
223 $pageId = $title->getArticleID();
224
225 // Check if article exists
226 if ( !$pageId ) {
227 return Status::newFatal(
228 'pagelang-nonexistent-page',
229 wfEscapeWikiText( $title->getPrefixedText() )
230 );
231 }
232
233 // Load the page language from DB
234 $dbw ??= wfGetDB( DB_PRIMARY );
235 $oldLanguage = $dbw->selectField(
236 'page',
237 'page_lang',
238 [ 'page_id' => $pageId ],
239 __METHOD__
240 );
241
242 // Check if user wants to use the default language
243 if ( $newLanguage === 'default' ) {
244 $newLanguage = null;
245 }
246
247 // No change in language
248 if ( $newLanguage === $oldLanguage ) {
249 // Check if old language does not exist
250 if ( !$oldLanguage ) {
251 return Status::newFatal( ApiMessage::create(
252 [
253 'pagelang-unchanged-language-default',
254 wfEscapeWikiText( $title->getPrefixedText() )
255 ],
256 'pagelang-unchanged-language'
257 ) );
258 }
259 return Status::newFatal(
260 'pagelang-unchanged-language',
261 wfEscapeWikiText( $title->getPrefixedText() ),
262 $oldLanguage
263 );
264 }
265
266 // Hardcoded [def] if the language is set to null
267 $logOld = $oldLanguage ?: $defLang . '[def]';
268 $logNew = $newLanguage ?: $defLang . '[def]';
269
270 // Writing new page language to database
271 $dbw->update(
272 'page',
273 [ 'page_lang' => $newLanguage ],
274 [
275 'page_id' => $pageId,
276 'page_lang' => $oldLanguage
277 ],
278 __METHOD__
279 );
280
281 if ( !$dbw->affectedRows() ) {
282 return Status::newFatal( 'pagelang-db-failed' );
283 }
284
285 // Logging change of language
286 $logParams = [
287 '4::oldlanguage' => $logOld,
288 '5::newlanguage' => $logNew
289 ];
290 $entry = new ManualLogEntry( 'pagelang', 'pagelang' );
291 $entry->setPerformer( $context->getUser() );
292 $entry->setTarget( $title );
293 $entry->setParameters( $logParams );
294 $entry->setComment( is_string( $reason ) ? $reason : "" );
295 $entry->addTags( $tags );
296
297 $logid = $entry->insert();
298 $entry->publish( $logid );
299
300 // Force re-render so that language-based content (parser functions etc.) gets updated
301 $title->invalidateCache();
302
303 return Status::newGood( (object)[
304 'oldLanguage' => $logOld,
305 'newLanguage' => $logNew,
306 'logId' => $logid,
307 ] );
308 }
309
310 public function onSuccess() {
311 // Success causes a redirect
312 $this->getOutput()->redirect( $this->goToUrl );
313 }
314
315 private function showLogFragment( $title ) {
316 $moveLogPage = new LogPage( 'pagelang' );
317 $out1 = Xml::element( 'h2', null, $moveLogPage->getName()->text() );
318 $out2 = '';
319 LogEventsList::showLogExtract( $out2, 'pagelang', $title );
320 return $out1 . $out2;
321 }
322
331 public function prefixSearchSubpages( $search, $limit, $offset ) {
332 return $this->prefixSearchString( $search, $limit, $offset, $this->searchEngineFactory );
333 }
334
335 protected function getGroupName() {
336 return 'pagetools';
337 }
338}
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:153
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Class to simplify the use of log pages.
Definition LogPage.php:41
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.
Variant of the Message class.
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.
Represents a title within MediaWiki.
Definition Title.php:82
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.
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:36
This class is a delegate to ILBFactory for a given database cluster.
const DB_PRIMARY
Definition defines.php:28