MediaWiki REL1_39
SpecialChangeContentModel.php
Go to the documentation of this file.
1<?php
2
10
12
14 private $contentHandlerFactory;
15
17 private $contentModelChangeFactory;
18
20 private $spamChecker;
21
23 private $revisionLookup;
24
26 private $wikiPageFactory;
27
29 private $searchEngineFactory;
30
39 public function __construct(
40 IContentHandlerFactory $contentHandlerFactory,
41 ContentModelChangeFactory $contentModelChangeFactory,
42 SpamChecker $spamChecker,
43 RevisionLookup $revisionLookup,
44 WikiPageFactory $wikiPageFactory,
45 SearchEngineFactory $searchEngineFactory
46 ) {
47 parent::__construct( 'ChangeContentModel', 'editcontentmodel' );
48
49 $this->contentHandlerFactory = $contentHandlerFactory;
50 $this->contentModelChangeFactory = $contentModelChangeFactory;
51 $this->spamChecker = $spamChecker;
52 $this->revisionLookup = $revisionLookup;
53 $this->wikiPageFactory = $wikiPageFactory;
54 $this->searchEngineFactory = $searchEngineFactory;
55 }
56
57 public function doesWrites() {
58 return true;
59 }
60
64 private $title;
65
71 private $oldRevision;
72
73 protected function setParameter( $par ) {
74 $par = $this->getRequest()->getVal( 'pagetitle', $par );
75 $title = Title::newFromText( $par );
76 if ( $title ) {
77 $this->title = $title;
78 $this->par = $title->getPrefixedText();
79 } else {
80 $this->par = '';
81 }
82 }
83
84 protected function postHtml() {
85 $text = '';
86 if ( $this->title ) {
87 $contentModelLogPage = new LogPage( 'contentmodel' );
88 $text = Xml::element( 'h2', null, $contentModelLogPage->getName()->text() );
89 $out = '';
90 LogEventsList::showLogExtract( $out, 'contentmodel', $this->title );
91 $text .= $out;
92 }
93 return $text;
94 }
95
96 protected function getDisplayFormat() {
97 return 'ooui';
98 }
99
100 protected function alterForm( HTMLForm $form ) {
101 $this->addHelpLink( 'Help:ChangeContentModel' );
102
103 if ( $this->title ) {
104 $form->setFormIdentifier( 'modelform' );
105 } else {
106 $form->setFormIdentifier( 'titleform' );
107 }
108
109 // T120576
110 $form->setSubmitTextMsg( 'changecontentmodel-submit' );
111
112 if ( $this->title ) {
113 $this->getOutput()->addBacklinkSubtitle( $this->title );
114 }
115 }
116
117 public function validateTitle( $title ) {
118 // Already validated by HTMLForm, but if not, throw
119 // an exception instead of a fatal
120 $titleObj = Title::newFromTextThrow( $title );
121
122 $this->oldRevision = $this->revisionLookup->getRevisionByTitle( $titleObj ) ?: false;
123
124 if ( $this->oldRevision ) {
125 $oldContent = $this->oldRevision->getContent( SlotRecord::MAIN );
126 if ( !$oldContent->getContentHandler()->supportsDirectEditing() ) {
127 return $this->msg( 'changecontentmodel-nodirectediting' )
128 ->params( ContentHandler::getLocalizedName( $oldContent->getModel() ) )
129 ->escaped();
130 }
131 }
132
133 return true;
134 }
135
136 protected function getFormFields() {
137 $fields = [
138 'pagetitle' => [
139 'type' => 'title',
140 'creatable' => true,
141 'name' => 'pagetitle',
142 'default' => $this->par,
143 'label-message' => 'changecontentmodel-title-label',
144 'validation-callback' => [ $this, 'validateTitle' ],
145 ],
146 ];
147 if ( $this->title ) {
148 $options = $this->getOptionsForTitle( $this->title );
149 if ( empty( $options ) ) {
150 throw new ErrorPageError(
151 'changecontentmodel-emptymodels-title',
152 'changecontentmodel-emptymodels-text',
153 [ $this->title->getPrefixedText() ]
154 );
155 }
156 $fields['pagetitle']['readonly'] = true;
157 $fields += [
158 'currentmodel' => [
159 'type' => 'text',
160 'name' => 'currentcontentmodel',
161 'default' => $this->title->getContentModel(),
162 'label-message' => 'changecontentmodel-current-label',
163 'readonly' => true
164 ],
165 'model' => [
166 'type' => 'select',
167 'name' => 'model',
168 'options' => $options,
169 'label-message' => 'changecontentmodel-model-label'
170 ],
171 'reason' => [
172 'type' => 'text',
173 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
174 'name' => 'reason',
175 'validation-callback' => function ( $reason ) {
176 if ( $reason === null || $reason === '' ) {
177 // Null on form display, or no reason given
178 return true;
179 }
180
181 $match = $this->spamChecker->checkSummary( $reason );
182
183 if ( $match ) {
184 return $this->msg( 'spamprotectionmatch', $match )->parse();
185 }
186
187 return true;
188 },
189 'label-message' => 'changecontentmodel-reason-label',
190 ],
191 ];
192 }
193
194 return $fields;
195 }
196
197 private function getOptionsForTitle( Title $title = null ) {
198 $models = $this->contentHandlerFactory->getContentModels();
199 $options = [];
200 foreach ( $models as $model ) {
201 $handler = $this->contentHandlerFactory->getContentHandler( $model );
202 if ( !$handler->supportsDirectEditing() ) {
203 continue;
204 }
205 if ( $title ) {
206 if ( $title->getContentModel() === $model ) {
207 continue;
208 }
209 if ( !$handler->canBeUsedOn( $title ) ) {
210 continue;
211 }
212 }
213 $options[ContentHandler::getLocalizedName( $model )] = $model;
214 }
215
216 return $options;
217 }
218
219 public function onSubmit( array $data ) {
220 $this->title = Title::newFromText( $data['pagetitle'] );
221 $page = $this->wikiPageFactory->newFromTitle( $this->title );
222
223 $changer = $this->contentModelChangeFactory->newContentModelChange(
224 $this->getContext()->getAuthority(),
225 $page,
226 $data['model']
227 );
228
229 $permissionStatus = $changer->authorizeChange();
230 if ( !$permissionStatus->isGood() ) {
231 $out = $this->getOutput();
232 $wikitext = $out->formatPermissionStatus( $permissionStatus );
233 // Hack to get our wikitext parsed
234 return Status::newFatal( new RawMessage( '$1', [ $wikitext ] ) );
235 }
236
237 // Can also throw a ThrottledError, don't catch it
238 $status = $changer->doContentModelChange(
239 $this->getContext(),
240 $data['reason'],
241 true
242 );
243
244 return $status;
245 }
246
247 public function onSuccess() {
248 $out = $this->getOutput();
249 $out->setPageTitle( $this->msg( 'changecontentmodel-success-title' ) );
250 $out->addWikiMsg( 'changecontentmodel-success-text', $this->title );
251 }
252
261 public function prefixSearchSubpages( $search, $limit, $offset ) {
262 return $this->prefixSearchString( $search, $limit, $offset, $this->searchEngineFactory );
263 }
264
265 protected function getGroupName() {
266 return 'pagetools';
267 }
268}
static getLocalizedName( $name, Language $lang=null)
Returns the localized name for a given content model.
An error page which can definitely be safely rendered using the OutputPage.
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.
setFormIdentifier( $ident)
Set an internal identifier for this form.
Class to simplify the use of log pages.
Definition LogPage.php:39
Service to check if text (either content or a summary) qualifies as spam.
Service for creating WikiPage objects.
Page revision base class.
Value object representing a content slot associated with a page revision.
Variant of the Message class.
Factory class for SearchEngine.
setParameter( $par)
Maybe do something interesting with the subpage parameter.
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getFormFields()
Get an HTMLForm descriptor array.
getDisplayFormat()
Get display format for the form.
doesWrites()
Indicates whether this special page may perform database writes.
onSubmit(array $data)
Process the form on POST submission.
postHtml()
Add post-HTML to the form.
__construct(IContentHandlerFactory $contentHandlerFactory, ContentModelChangeFactory $contentModelChangeFactory, SpamChecker $spamChecker, RevisionLookup $revisionLookup, WikiPageFactory $wikiPageFactory, SearchEngineFactory $searchEngineFactory)
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
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.
getRequest()
Get the WebRequest being used for this instance.
prefixSearchString( $search, $limit, $offset, SearchEngineFactory $searchEngineFactory=null)
Perform a regular substring search for prefixSearchSubpages.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Represents a title within MediaWiki.
Definition Title.php:49
getContentModel( $flags=0)
Get the page's content model id, see the CONTENT_MODEL_XXX constants.
Definition Title.php:1088
getPrefixedText()
Get the prefixed title with spaces.
Definition Title.php:1890
Service for changing the content model of wiki pages.
Service for looking up page revisions.
return true
Definition router.php:92