|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Implements Special:Movepage |
|
4
|
|
|
* |
|
5
|
|
|
* This program is free software; you can redistribute it and/or modify |
|
6
|
|
|
* it under the terms of the GNU General Public License as published by |
|
7
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
|
8
|
|
|
* (at your option) any later version. |
|
9
|
|
|
* |
|
10
|
|
|
* This program is distributed in the hope that it will be useful, |
|
11
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13
|
|
|
* GNU General Public License for more details. |
|
14
|
|
|
* |
|
15
|
|
|
* You should have received a copy of the GNU General Public License along |
|
16
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc., |
|
17
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
18
|
|
|
* http://www.gnu.org/copyleft/gpl.html |
|
19
|
|
|
* |
|
20
|
|
|
* @file |
|
21
|
|
|
* @ingroup SpecialPage |
|
22
|
|
|
*/ |
|
23
|
|
|
|
|
24
|
|
|
/** |
|
25
|
|
|
* A special page that allows users to change page titles |
|
26
|
|
|
* |
|
27
|
|
|
* @ingroup SpecialPage |
|
28
|
|
|
*/ |
|
29
|
|
|
class MovePageForm extends UnlistedSpecialPage { |
|
30
|
|
|
/** @var Title */ |
|
31
|
|
|
protected $oldTitle = null; |
|
32
|
|
|
|
|
33
|
|
|
/** @var Title */ |
|
34
|
|
|
protected $newTitle; |
|
35
|
|
|
|
|
36
|
|
|
/** @var string Text input */ |
|
37
|
|
|
protected $reason; |
|
38
|
|
|
|
|
39
|
|
|
// Checks |
|
40
|
|
|
|
|
41
|
|
|
/** @var bool */ |
|
42
|
|
|
protected $moveTalk; |
|
43
|
|
|
|
|
44
|
|
|
/** @var bool */ |
|
45
|
|
|
protected $deleteAndMove; |
|
46
|
|
|
|
|
47
|
|
|
/** @var bool */ |
|
48
|
|
|
protected $moveSubpages; |
|
49
|
|
|
|
|
50
|
|
|
/** @var bool */ |
|
51
|
|
|
protected $fixRedirects; |
|
52
|
|
|
|
|
53
|
|
|
/** @var bool */ |
|
54
|
|
|
protected $leaveRedirect; |
|
55
|
|
|
|
|
56
|
|
|
/** @var bool */ |
|
57
|
|
|
protected $moveOverShared; |
|
58
|
|
|
|
|
59
|
|
|
private $watch = false; |
|
60
|
|
|
|
|
61
|
|
|
public function __construct() { |
|
62
|
|
|
parent::__construct( 'Movepage' ); |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
public function doesWrites() { |
|
66
|
|
|
return true; |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
public function execute( $par ) { |
|
70
|
|
|
$this->useTransactionalTimeLimit(); |
|
71
|
|
|
|
|
72
|
|
|
$this->checkReadOnly(); |
|
73
|
|
|
|
|
74
|
|
|
$this->setHeaders(); |
|
75
|
|
|
$this->outputHeader(); |
|
76
|
|
|
|
|
77
|
|
|
$request = $this->getRequest(); |
|
78
|
|
|
$target = !is_null( $par ) ? $par : $request->getVal( 'target' ); |
|
79
|
|
|
|
|
80
|
|
|
// Yes, the use of getVal() and getText() is wanted, see bug 20365 |
|
81
|
|
|
|
|
82
|
|
|
$oldTitleText = $request->getVal( 'wpOldTitle', $target ); |
|
83
|
|
|
$this->oldTitle = Title::newFromText( $oldTitleText ); |
|
84
|
|
|
|
|
85
|
|
|
if ( !$this->oldTitle ) { |
|
86
|
|
|
// Either oldTitle wasn't passed, or newFromText returned null |
|
87
|
|
|
throw new ErrorPageError( 'notargettitle', 'notargettext' ); |
|
88
|
|
|
} |
|
89
|
|
|
if ( !$this->oldTitle->exists() ) { |
|
90
|
|
|
throw new ErrorPageError( 'nopagetitle', 'nopagetext' ); |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
$newTitleTextMain = $request->getText( 'wpNewTitleMain' ); |
|
94
|
|
|
$newTitleTextNs = $request->getInt( 'wpNewTitleNs', $this->oldTitle->getNamespace() ); |
|
95
|
|
|
// Backwards compatibility for forms submitting here from other sources |
|
96
|
|
|
// which is more common than it should be.. |
|
97
|
|
|
$newTitleText_bc = $request->getText( 'wpNewTitle' ); |
|
98
|
|
|
$this->newTitle = strlen( $newTitleText_bc ) > 0 |
|
99
|
|
|
? Title::newFromText( $newTitleText_bc ) |
|
100
|
|
|
: Title::makeTitleSafe( $newTitleTextNs, $newTitleTextMain ); |
|
101
|
|
|
|
|
102
|
|
|
$user = $this->getUser(); |
|
103
|
|
|
|
|
104
|
|
|
# Check rights |
|
105
|
|
|
$permErrors = $this->oldTitle->getUserPermissionsErrors( 'move', $user ); |
|
106
|
|
|
if ( count( $permErrors ) ) { |
|
107
|
|
|
// Auto-block user's IP if the account was "hard" blocked |
|
108
|
|
|
DeferredUpdates::addCallableUpdate( function() use ( $user ) { |
|
109
|
|
|
$user->spreadAnyEditBlock(); |
|
110
|
|
|
} ); |
|
111
|
|
|
throw new PermissionsError( 'move', $permErrors ); |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
$def = !$request->wasPosted(); |
|
115
|
|
|
|
|
116
|
|
|
$this->reason = $request->getText( 'wpReason' ); |
|
117
|
|
|
$this->moveTalk = $request->getBool( 'wpMovetalk', $def ); |
|
118
|
|
|
$this->fixRedirects = $request->getBool( 'wpFixRedirects', $def ); |
|
119
|
|
|
$this->leaveRedirect = $request->getBool( 'wpLeaveRedirect', $def ); |
|
120
|
|
|
$this->moveSubpages = $request->getBool( 'wpMovesubpages' ); |
|
121
|
|
|
$this->deleteAndMove = $request->getBool( 'wpDeleteAndMove' ); |
|
122
|
|
|
$this->moveOverShared = $request->getBool( 'wpMoveOverSharedFile' ); |
|
123
|
|
|
$this->watch = $request->getCheck( 'wpWatch' ) && $user->isLoggedIn(); |
|
124
|
|
|
|
|
125
|
|
|
if ( 'submit' == $request->getVal( 'action' ) && $request->wasPosted() |
|
126
|
|
|
&& $user->matchEditToken( $request->getVal( 'wpEditToken' ) ) |
|
127
|
|
|
) { |
|
128
|
|
|
$this->doSubmit(); |
|
129
|
|
|
} else { |
|
130
|
|
|
$this->showForm( [] ); |
|
131
|
|
|
} |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* Show the form |
|
136
|
|
|
* |
|
137
|
|
|
* @param array $err Error messages. Each item is an error message. |
|
138
|
|
|
* It may either be a string message name or array message name and |
|
139
|
|
|
* parameters, like the second argument to OutputPage::wrapWikiMsg(). |
|
140
|
|
|
*/ |
|
141
|
|
|
function showForm( $err ) { |
|
142
|
|
|
global $wgContLang; |
|
143
|
|
|
|
|
144
|
|
|
$this->getSkin()->setRelevantTitle( $this->oldTitle ); |
|
145
|
|
|
|
|
146
|
|
|
$out = $this->getOutput(); |
|
147
|
|
|
$out->setPageTitle( $this->msg( 'move-page', $this->oldTitle->getPrefixedText() ) ); |
|
148
|
|
|
$out->addModules( 'mediawiki.special.movePage' ); |
|
149
|
|
|
$out->addModuleStyles( 'mediawiki.special.movePage.styles' ); |
|
150
|
|
|
$this->addHelpLink( 'Help:Moving a page' ); |
|
151
|
|
|
|
|
152
|
|
|
$out->addWikiMsg( $this->getConfig()->get( 'FixDoubleRedirects' ) ? |
|
153
|
|
|
'movepagetext' : |
|
154
|
|
|
'movepagetext-noredirectfixer' |
|
155
|
|
|
); |
|
156
|
|
|
|
|
157
|
|
|
if ( $this->oldTitle->getNamespace() == NS_USER && !$this->oldTitle->isSubpage() ) { |
|
158
|
|
|
$out->wrapWikiMsg( |
|
159
|
|
|
"<div class=\"warningbox mw-moveuserpage-warning\">\n$1\n</div>", |
|
160
|
|
|
'moveuserpage-warning' |
|
161
|
|
|
); |
|
162
|
|
|
} elseif ( $this->oldTitle->getNamespace() == NS_CATEGORY ) { |
|
163
|
|
|
$out->wrapWikiMsg( |
|
164
|
|
|
"<div class=\"warningbox mw-movecategorypage-warning\">\n$1\n</div>", |
|
165
|
|
|
'movecategorypage-warning' |
|
166
|
|
|
); |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
$deleteAndMove = false; |
|
170
|
|
|
$moveOverShared = false; |
|
171
|
|
|
|
|
172
|
|
|
$newTitle = $this->newTitle; |
|
173
|
|
|
|
|
174
|
|
|
if ( !$newTitle ) { |
|
175
|
|
|
# Show the current title as a default |
|
176
|
|
|
# when the form is first opened. |
|
177
|
|
|
$newTitle = $this->oldTitle; |
|
178
|
|
|
} elseif ( !count( $err ) ) { |
|
179
|
|
|
# If a title was supplied, probably from the move log revert |
|
180
|
|
|
# link, check for validity. We can then show some diagnostic |
|
181
|
|
|
# information and save a click. |
|
182
|
|
|
$newerr = $this->oldTitle->isValidMoveOperation( $newTitle ); |
|
|
|
|
|
|
183
|
|
|
if ( is_array( $newerr ) ) { |
|
184
|
|
|
$err = $newerr; |
|
185
|
|
|
} |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
$user = $this->getUser(); |
|
189
|
|
|
|
|
190
|
|
View Code Duplication |
if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'articleexists' |
|
191
|
|
|
&& $newTitle->quickUserCan( 'delete', $user ) |
|
192
|
|
|
) { |
|
193
|
|
|
$out->wrapWikiMsg( |
|
194
|
|
|
"<div class='warningbox'>\n$1\n</div>\n", |
|
195
|
|
|
[ 'delete_and_move_text', $newTitle->getPrefixedText() ] |
|
196
|
|
|
); |
|
197
|
|
|
$deleteAndMove = true; |
|
198
|
|
|
$err = []; |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
|
View Code Duplication |
if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'file-exists-sharedrepo' |
|
202
|
|
|
&& $user->isAllowed( 'reupload-shared' ) |
|
203
|
|
|
) { |
|
204
|
|
|
$out->wrapWikiMsg( |
|
205
|
|
|
"<div class='warningbox'>\n$1\n</div>\n", |
|
206
|
|
|
[ |
|
207
|
|
|
'move-over-sharedrepo', |
|
208
|
|
|
$newTitle->getPrefixedText() |
|
209
|
|
|
] |
|
210
|
|
|
); |
|
211
|
|
|
$moveOverShared = true; |
|
212
|
|
|
$err = []; |
|
213
|
|
|
} |
|
214
|
|
|
|
|
215
|
|
|
$oldTalk = $this->oldTitle->getTalkPage(); |
|
216
|
|
|
$oldTitleSubpages = $this->oldTitle->hasSubpages(); |
|
217
|
|
|
$oldTitleTalkSubpages = $this->oldTitle->getTalkPage()->hasSubpages(); |
|
218
|
|
|
|
|
219
|
|
|
$canMoveSubpage = ( $oldTitleSubpages || $oldTitleTalkSubpages ) && |
|
220
|
|
|
!count( $this->oldTitle->getUserPermissionsErrors( 'move-subpages', $user ) ); |
|
221
|
|
|
|
|
222
|
|
|
# We also want to be able to move assoc. subpage talk-pages even if base page |
|
223
|
|
|
# has no associated talk page, so || with $oldTitleTalkSubpages. |
|
224
|
|
|
$considerTalk = !$this->oldTitle->isTalkPage() && |
|
225
|
|
|
( $oldTalk->exists() |
|
226
|
|
|
|| ( $oldTitleTalkSubpages && $canMoveSubpage ) ); |
|
227
|
|
|
|
|
228
|
|
|
$dbr = wfGetDB( DB_SLAVE ); |
|
229
|
|
|
if ( $this->getConfig()->get( 'FixDoubleRedirects' ) ) { |
|
230
|
|
|
$hasRedirects = $dbr->selectField( 'redirect', '1', |
|
231
|
|
|
[ |
|
232
|
|
|
'rd_namespace' => $this->oldTitle->getNamespace(), |
|
233
|
|
|
'rd_title' => $this->oldTitle->getDBkey(), |
|
234
|
|
|
], __METHOD__ ); |
|
235
|
|
|
} else { |
|
236
|
|
|
$hasRedirects = false; |
|
237
|
|
|
} |
|
238
|
|
|
|
|
239
|
|
|
if ( count( $err ) ) { |
|
240
|
|
|
$out->addHTML( "<div class='errorbox'>\n" ); |
|
241
|
|
|
$action_desc = $this->msg( 'action-move' )->plain(); |
|
242
|
|
|
$out->addWikiMsg( 'permissionserrorstext-withaction', count( $err ), $action_desc ); |
|
243
|
|
|
|
|
244
|
|
|
if ( count( $err ) == 1 ) { |
|
245
|
|
|
$errMsg = $err[0]; |
|
246
|
|
|
$errMsgName = array_shift( $errMsg ); |
|
247
|
|
|
|
|
248
|
|
|
if ( $errMsgName == 'hookaborted' ) { |
|
249
|
|
|
$out->addHTML( "<p>{$errMsg[0]}</p>\n" ); |
|
250
|
|
|
} else { |
|
251
|
|
|
$out->addWikiMsgArray( $errMsgName, $errMsg ); |
|
252
|
|
|
} |
|
253
|
|
|
} else { |
|
254
|
|
|
$errStr = []; |
|
255
|
|
|
|
|
256
|
|
|
foreach ( $err as $errMsg ) { |
|
257
|
|
|
if ( $errMsg[0] == 'hookaborted' ) { |
|
258
|
|
|
$errStr[] = $errMsg[1]; |
|
259
|
|
|
} else { |
|
260
|
|
|
$errMsgName = array_shift( $errMsg ); |
|
261
|
|
|
$errStr[] = $this->msg( $errMsgName, $errMsg )->parse(); |
|
262
|
|
|
} |
|
263
|
|
|
} |
|
264
|
|
|
|
|
265
|
|
|
$out->addHTML( '<ul><li>' . implode( "</li>\n<li>", $errStr ) . "</li></ul>\n" ); |
|
266
|
|
|
} |
|
267
|
|
|
$out->addHTML( "</div>\n" ); |
|
268
|
|
|
} |
|
269
|
|
|
|
|
270
|
|
|
if ( $this->oldTitle->isProtected( 'move' ) ) { |
|
271
|
|
|
# Is the title semi-protected? |
|
272
|
|
|
if ( $this->oldTitle->isSemiProtected( 'move' ) ) { |
|
273
|
|
|
$noticeMsg = 'semiprotectedpagemovewarning'; |
|
274
|
|
|
$classes[] = 'mw-textarea-sprotected'; |
|
|
|
|
|
|
275
|
|
|
} else { |
|
276
|
|
|
# Then it must be protected based on static groups (regular) |
|
277
|
|
|
$noticeMsg = 'protectedpagemovewarning'; |
|
278
|
|
|
$classes[] = 'mw-textarea-protected'; |
|
|
|
|
|
|
279
|
|
|
} |
|
280
|
|
|
$out->addHTML( "<div class='mw-warning-with-logexcerpt'>\n" ); |
|
281
|
|
|
$out->addWikiMsg( $noticeMsg ); |
|
282
|
|
|
LogEventsList::showLogExtract( |
|
283
|
|
|
$out, |
|
284
|
|
|
'protect', |
|
285
|
|
|
$this->oldTitle, |
|
286
|
|
|
'', |
|
287
|
|
|
[ 'lim' => 1 ] |
|
288
|
|
|
); |
|
289
|
|
|
$out->addHTML( "</div>\n" ); |
|
290
|
|
|
} |
|
291
|
|
|
|
|
292
|
|
|
// Byte limit (not string length limit) for wpReason and wpNewTitleMain |
|
293
|
|
|
// is enforced in the mediawiki.special.movePage module |
|
294
|
|
|
|
|
295
|
|
|
$immovableNamespaces = []; |
|
296
|
|
|
foreach ( array_keys( $this->getLanguage()->getNamespaces() ) as $nsId ) { |
|
297
|
|
|
if ( !MWNamespace::isMovable( $nsId ) ) { |
|
298
|
|
|
$immovableNamespaces[] = $nsId; |
|
299
|
|
|
} |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
$handler = ContentHandler::getForTitle( $this->oldTitle ); |
|
303
|
|
|
|
|
304
|
|
|
$out->enableOOUI(); |
|
305
|
|
|
$fields = []; |
|
306
|
|
|
|
|
307
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
308
|
|
|
new MediaWiki\Widget\ComplexTitleInputWidget( [ |
|
309
|
|
|
'id' => 'wpNewTitle', |
|
310
|
|
|
'namespace' => [ |
|
311
|
|
|
'id' => 'wpNewTitleNs', |
|
312
|
|
|
'name' => 'wpNewTitleNs', |
|
313
|
|
|
'value' => $newTitle->getNamespace(), |
|
314
|
|
|
'exclude' => $immovableNamespaces, |
|
315
|
|
|
], |
|
316
|
|
|
'title' => [ |
|
317
|
|
|
'id' => 'wpNewTitleMain', |
|
318
|
|
|
'name' => 'wpNewTitleMain', |
|
319
|
|
|
'value' => $wgContLang->recodeForEdit( $newTitle->getText() ), |
|
320
|
|
|
// Inappropriate, since we're expecting the user to input a non-existent page's title |
|
321
|
|
|
'suggestions' => false, |
|
322
|
|
|
], |
|
323
|
|
|
'infusable' => true, |
|
324
|
|
|
] ), |
|
325
|
|
|
[ |
|
326
|
|
|
'label' => $this->msg( 'newtitle' )->text(), |
|
327
|
|
|
'align' => 'top', |
|
328
|
|
|
] |
|
329
|
|
|
); |
|
330
|
|
|
|
|
331
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
332
|
|
|
new OOUI\TextInputWidget( [ |
|
333
|
|
|
'name' => 'wpReason', |
|
334
|
|
|
'id' => 'wpReason', |
|
335
|
|
|
'maxLength' => 200, |
|
336
|
|
|
'infusable' => true, |
|
337
|
|
|
'value' => $this->reason, |
|
338
|
|
|
] ), |
|
339
|
|
|
[ |
|
340
|
|
|
'label' => $this->msg( 'movereason' )->text(), |
|
341
|
|
|
'align' => 'top', |
|
342
|
|
|
] |
|
343
|
|
|
); |
|
344
|
|
|
|
|
345
|
|
|
if ( $considerTalk ) { |
|
346
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
347
|
|
|
new OOUI\CheckboxInputWidget( [ |
|
348
|
|
|
'name' => 'wpMovetalk', |
|
349
|
|
|
'id' => 'wpMovetalk', |
|
350
|
|
|
'value' => '1', |
|
351
|
|
|
'selected' => $this->moveTalk, |
|
352
|
|
|
] ), |
|
353
|
|
|
[ |
|
354
|
|
|
'label' => $this->msg( 'movetalk' )->text(), |
|
355
|
|
|
'help' => new OOUI\HtmlSnippet( $this->msg( 'movepagetalktext' )->parseAsBlock() ), |
|
356
|
|
|
'align' => 'inline', |
|
357
|
|
|
'infusable' => true, |
|
358
|
|
|
] |
|
359
|
|
|
); |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
|
|
if ( $user->isAllowed( 'suppressredirect' ) ) { |
|
363
|
|
|
if ( $handler->supportsRedirects() ) { |
|
364
|
|
|
$isChecked = $this->leaveRedirect; |
|
365
|
|
|
$isDisabled = false; |
|
366
|
|
|
} else { |
|
367
|
|
|
$isChecked = false; |
|
368
|
|
|
$isDisabled = true; |
|
369
|
|
|
} |
|
370
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
371
|
|
|
new OOUI\CheckboxInputWidget( [ |
|
372
|
|
|
'name' => 'wpLeaveRedirect', |
|
373
|
|
|
'id' => 'wpLeaveRedirect', |
|
374
|
|
|
'value' => '1', |
|
375
|
|
|
'selected' => $isChecked, |
|
376
|
|
|
'disabled' => $isDisabled, |
|
377
|
|
|
] ), |
|
378
|
|
|
[ |
|
379
|
|
|
'label' => $this->msg( 'move-leave-redirect' )->text(), |
|
380
|
|
|
'align' => 'inline', |
|
381
|
|
|
] |
|
382
|
|
|
); |
|
383
|
|
|
} |
|
384
|
|
|
|
|
385
|
|
View Code Duplication |
if ( $hasRedirects ) { |
|
386
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
387
|
|
|
new OOUI\CheckboxInputWidget( [ |
|
388
|
|
|
'name' => 'wpFixRedirects', |
|
389
|
|
|
'id' => 'wpFixRedirects', |
|
390
|
|
|
'value' => '1', |
|
391
|
|
|
'selected' => $this->fixRedirects, |
|
392
|
|
|
] ), |
|
393
|
|
|
[ |
|
394
|
|
|
'label' => $this->msg( 'fix-double-redirects' )->text(), |
|
395
|
|
|
'align' => 'inline', |
|
396
|
|
|
] |
|
397
|
|
|
); |
|
398
|
|
|
} |
|
399
|
|
|
|
|
400
|
|
|
if ( $canMoveSubpage ) { |
|
401
|
|
|
$maximumMovedPages = $this->getConfig()->get( 'MaximumMovedPages' ); |
|
402
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
403
|
|
|
new OOUI\CheckboxInputWidget( [ |
|
404
|
|
|
'name' => 'wpMovesubpages', |
|
405
|
|
|
'id' => 'wpMovesubpages', |
|
406
|
|
|
'value' => '1', |
|
407
|
|
|
# Don't check the box if we only have talk subpages to |
|
408
|
|
|
# move and we aren't moving the talk page. |
|
409
|
|
|
'selected' => $this->moveSubpages && ( $this->oldTitle->hasSubpages() || $this->moveTalk ), |
|
410
|
|
|
] ), |
|
411
|
|
|
[ |
|
412
|
|
|
'label' => new OOUI\HtmlSnippet( |
|
413
|
|
|
$this->msg( |
|
414
|
|
|
( $this->oldTitle->hasSubpages() |
|
415
|
|
|
? 'move-subpages' |
|
416
|
|
|
: 'move-talk-subpages' ) |
|
417
|
|
|
)->numParams( $maximumMovedPages )->params( $maximumMovedPages )->parse() |
|
418
|
|
|
), |
|
419
|
|
|
'align' => 'inline', |
|
420
|
|
|
] |
|
421
|
|
|
); |
|
422
|
|
|
} |
|
423
|
|
|
|
|
424
|
|
|
# Don't allow watching if user is not logged in |
|
425
|
|
|
if ( $user->isLoggedIn() ) { |
|
426
|
|
|
$watchChecked = $user->isLoggedIn() && ( $this->watch || $user->getBoolOption( 'watchmoves' ) |
|
427
|
|
|
|| $user->isWatched( $this->oldTitle ) ); |
|
428
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
429
|
|
|
new OOUI\CheckboxInputWidget( [ |
|
430
|
|
|
'name' => 'wpWatch', |
|
431
|
|
|
'id' => 'watch', # ew |
|
432
|
|
|
'value' => '1', |
|
433
|
|
|
'selected' => $watchChecked, |
|
434
|
|
|
] ), |
|
435
|
|
|
[ |
|
436
|
|
|
'label' => $this->msg( 'move-watch' )->text(), |
|
437
|
|
|
'align' => 'inline', |
|
438
|
|
|
] |
|
439
|
|
|
); |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
$hiddenFields = ''; |
|
443
|
|
|
if ( $moveOverShared ) { |
|
444
|
|
|
$hiddenFields .= Html::hidden( 'wpMoveOverSharedFile', '1' ); |
|
445
|
|
|
} |
|
446
|
|
|
|
|
447
|
|
View Code Duplication |
if ( $deleteAndMove ) { |
|
448
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
449
|
|
|
new OOUI\CheckboxInputWidget( [ |
|
450
|
|
|
'name' => 'wpDeleteAndMove', |
|
451
|
|
|
'id' => 'wpDeleteAndMove', |
|
452
|
|
|
'value' => '1', |
|
453
|
|
|
] ), |
|
454
|
|
|
[ |
|
455
|
|
|
'label' => $this->msg( 'delete_and_move_confirm' )->text(), |
|
456
|
|
|
'align' => 'inline', |
|
457
|
|
|
] |
|
458
|
|
|
); |
|
459
|
|
|
} |
|
460
|
|
|
|
|
461
|
|
|
$fields[] = new OOUI\FieldLayout( |
|
462
|
|
|
new OOUI\ButtonInputWidget( [ |
|
463
|
|
|
'name' => 'wpMove', |
|
464
|
|
|
'value' => $this->msg( 'movepagebtn' )->text(), |
|
465
|
|
|
'label' => $this->msg( 'movepagebtn' )->text(), |
|
466
|
|
|
'flags' => [ 'constructive', 'primary' ], |
|
467
|
|
|
'type' => 'submit', |
|
468
|
|
|
] ), |
|
469
|
|
|
[ |
|
470
|
|
|
'align' => 'top', |
|
471
|
|
|
] |
|
472
|
|
|
); |
|
473
|
|
|
|
|
474
|
|
|
$fieldset = new OOUI\FieldsetLayout( [ |
|
475
|
|
|
'label' => $this->msg( 'move-page-legend' )->text(), |
|
476
|
|
|
'id' => 'mw-movepage-table', |
|
477
|
|
|
'items' => $fields, |
|
478
|
|
|
] ); |
|
479
|
|
|
|
|
480
|
|
|
$form = new OOUI\FormLayout( [ |
|
481
|
|
|
'method' => 'post', |
|
482
|
|
|
'action' => $this->getPageTitle()->getLocalURL( 'action=submit' ), |
|
483
|
|
|
'id' => 'movepage', |
|
484
|
|
|
] ); |
|
485
|
|
|
$form->appendContent( |
|
486
|
|
|
$fieldset, |
|
487
|
|
|
new OOUI\HtmlSnippet( |
|
488
|
|
|
$hiddenFields . |
|
489
|
|
|
Html::hidden( 'wpOldTitle', $this->oldTitle->getPrefixedText() ) . |
|
490
|
|
|
Html::hidden( 'wpEditToken', $user->getEditToken() ) |
|
491
|
|
|
) |
|
492
|
|
|
); |
|
493
|
|
|
|
|
494
|
|
|
$out->addHTML( |
|
495
|
|
|
new OOUI\PanelLayout( [ |
|
496
|
|
|
'classes' => [ 'movepage-wrapper' ], |
|
497
|
|
|
'expanded' => false, |
|
498
|
|
|
'padded' => true, |
|
499
|
|
|
'framed' => true, |
|
500
|
|
|
'content' => $form, |
|
501
|
|
|
] ) |
|
502
|
|
|
); |
|
503
|
|
|
|
|
504
|
|
|
$this->showLogFragment( $this->oldTitle ); |
|
505
|
|
|
$this->showSubpages( $this->oldTitle ); |
|
506
|
|
|
} |
|
507
|
|
|
|
|
508
|
|
|
function doSubmit() { |
|
509
|
|
|
$user = $this->getUser(); |
|
510
|
|
|
|
|
511
|
|
|
if ( $user->pingLimiter( 'move' ) ) { |
|
512
|
|
|
throw new ThrottledError; |
|
513
|
|
|
} |
|
514
|
|
|
|
|
515
|
|
|
$ot = $this->oldTitle; |
|
516
|
|
|
$nt = $this->newTitle; |
|
517
|
|
|
|
|
518
|
|
|
# don't allow moving to pages with # in |
|
519
|
|
|
if ( !$nt || $nt->hasFragment() ) { |
|
520
|
|
|
$this->showForm( [ [ 'badtitletext' ] ] ); |
|
521
|
|
|
|
|
522
|
|
|
return; |
|
523
|
|
|
} |
|
524
|
|
|
|
|
525
|
|
|
# Show a warning if the target file exists on a shared repo |
|
526
|
|
|
if ( $nt->getNamespace() == NS_FILE |
|
527
|
|
|
&& !( $this->moveOverShared && $user->isAllowed( 'reupload-shared' ) ) |
|
528
|
|
|
&& !RepoGroup::singleton()->getLocalRepo()->findFile( $nt ) |
|
529
|
|
|
&& wfFindFile( $nt ) |
|
530
|
|
|
) { |
|
531
|
|
|
$this->showForm( [ [ 'file-exists-sharedrepo' ] ] ); |
|
532
|
|
|
|
|
533
|
|
|
return; |
|
534
|
|
|
} |
|
535
|
|
|
|
|
536
|
|
|
# Delete to make way if requested |
|
537
|
|
|
if ( $this->deleteAndMove ) { |
|
538
|
|
|
$permErrors = $nt->getUserPermissionsErrors( 'delete', $user ); |
|
539
|
|
|
if ( count( $permErrors ) ) { |
|
540
|
|
|
# Only show the first error |
|
541
|
|
|
$this->showForm( $permErrors ); |
|
542
|
|
|
|
|
543
|
|
|
return; |
|
544
|
|
|
} |
|
545
|
|
|
|
|
546
|
|
|
$reason = $this->msg( 'delete_and_move_reason', $ot )->inContentLanguage()->text(); |
|
547
|
|
|
|
|
548
|
|
|
// Delete an associated image if there is |
|
549
|
|
|
if ( $nt->getNamespace() == NS_FILE ) { |
|
550
|
|
|
$file = wfLocalFile( $nt ); |
|
551
|
|
|
$file->load( File::READ_LATEST ); |
|
552
|
|
|
if ( $file->exists() ) { |
|
553
|
|
|
$file->delete( $reason, false, $user ); |
|
554
|
|
|
} |
|
555
|
|
|
} |
|
556
|
|
|
|
|
557
|
|
|
$error = ''; // passed by ref |
|
558
|
|
|
$page = WikiPage::factory( $nt ); |
|
559
|
|
|
$deleteStatus = $page->doDeleteArticleReal( $reason, false, 0, true, $error, $user ); |
|
560
|
|
|
if ( !$deleteStatus->isGood() ) { |
|
561
|
|
|
$this->showForm( $deleteStatus->getErrorsArray() ); |
|
|
|
|
|
|
562
|
|
|
|
|
563
|
|
|
return; |
|
564
|
|
|
} |
|
565
|
|
|
} |
|
566
|
|
|
|
|
567
|
|
|
$handler = ContentHandler::getForTitle( $ot ); |
|
568
|
|
|
|
|
569
|
|
|
if ( !$handler->supportsRedirects() ) { |
|
570
|
|
|
$createRedirect = false; |
|
571
|
|
|
} elseif ( $user->isAllowed( 'suppressredirect' ) ) { |
|
572
|
|
|
$createRedirect = $this->leaveRedirect; |
|
573
|
|
|
} else { |
|
574
|
|
|
$createRedirect = true; |
|
575
|
|
|
} |
|
576
|
|
|
|
|
577
|
|
|
# Do the actual move. |
|
578
|
|
|
$mp = new MovePage( $ot, $nt ); |
|
579
|
|
|
$valid = $mp->isValidMove(); |
|
580
|
|
|
if ( !$valid->isOK() ) { |
|
581
|
|
|
$this->showForm( $valid->getErrorsArray() ); |
|
|
|
|
|
|
582
|
|
|
return; |
|
583
|
|
|
} |
|
584
|
|
|
|
|
585
|
|
|
$permStatus = $mp->checkPermissions( $user, $this->reason ); |
|
586
|
|
|
if ( !$permStatus->isOK() ) { |
|
587
|
|
|
$this->showForm( $permStatus->getErrorsArray() ); |
|
|
|
|
|
|
588
|
|
|
return; |
|
589
|
|
|
} |
|
590
|
|
|
|
|
591
|
|
|
$status = $mp->move( $user, $this->reason, $createRedirect ); |
|
592
|
|
|
if ( !$status->isOK() ) { |
|
593
|
|
|
$this->showForm( $status->getErrorsArray() ); |
|
|
|
|
|
|
594
|
|
|
return; |
|
595
|
|
|
} |
|
596
|
|
|
|
|
597
|
|
|
if ( $this->getConfig()->get( 'FixDoubleRedirects' ) && $this->fixRedirects ) { |
|
598
|
|
|
DoubleRedirectJob::fixRedirects( 'move', $ot, $nt ); |
|
599
|
|
|
} |
|
600
|
|
|
|
|
601
|
|
|
$out = $this->getOutput(); |
|
602
|
|
|
$out->setPageTitle( $this->msg( 'pagemovedsub' ) ); |
|
603
|
|
|
|
|
604
|
|
|
$linkRenderer = $this->getLinkRenderer(); |
|
605
|
|
|
$oldLink = $linkRenderer->makeLink( |
|
606
|
|
|
$ot, |
|
607
|
|
|
null, |
|
608
|
|
|
[ 'id' => 'movepage-oldlink' ], |
|
609
|
|
|
[ 'redirect' => 'no' ] |
|
610
|
|
|
); |
|
611
|
|
|
$newLink = $linkRenderer->makeKnownLink( |
|
612
|
|
|
$nt, |
|
613
|
|
|
null, |
|
614
|
|
|
[ 'id' => 'movepage-newlink' ] |
|
615
|
|
|
); |
|
616
|
|
|
$oldText = $ot->getPrefixedText(); |
|
617
|
|
|
$newText = $nt->getPrefixedText(); |
|
618
|
|
|
|
|
619
|
|
|
if ( $ot->exists() ) { |
|
620
|
|
|
// NOTE: we assume that if the old title exists, it's because it was re-created as |
|
621
|
|
|
// a redirect to the new title. This is not safe, but what we did before was |
|
622
|
|
|
// even worse: we just determined whether a redirect should have been created, |
|
623
|
|
|
// and reported that it was created if it should have, without any checks. |
|
624
|
|
|
// Also note that isRedirect() is unreliable because of bug 37209. |
|
625
|
|
|
$msgName = 'movepage-moved-redirect'; |
|
626
|
|
|
} else { |
|
627
|
|
|
$msgName = 'movepage-moved-noredirect'; |
|
628
|
|
|
} |
|
629
|
|
|
|
|
630
|
|
|
$out->addHTML( $this->msg( 'movepage-moved' )->rawParams( $oldLink, |
|
631
|
|
|
$newLink )->params( $oldText, $newText )->parseAsBlock() ); |
|
632
|
|
|
$out->addWikiMsg( $msgName ); |
|
633
|
|
|
|
|
634
|
|
|
Hooks::run( 'SpecialMovepageAfterMove', [ &$this, &$ot, &$nt ] ); |
|
635
|
|
|
|
|
636
|
|
|
# Now we move extra pages we've been asked to move: subpages and talk |
|
637
|
|
|
# pages. First, if the old page or the new page is a talk page, we |
|
638
|
|
|
# can't move any talk pages: cancel that. |
|
639
|
|
|
if ( $ot->isTalkPage() || $nt->isTalkPage() ) { |
|
640
|
|
|
$this->moveTalk = false; |
|
641
|
|
|
} |
|
642
|
|
|
|
|
643
|
|
|
if ( count( $ot->getUserPermissionsErrors( 'move-subpages', $user ) ) ) { |
|
644
|
|
|
$this->moveSubpages = false; |
|
645
|
|
|
} |
|
646
|
|
|
|
|
647
|
|
|
/** |
|
648
|
|
|
* Next make a list of id's. This might be marginally less efficient |
|
649
|
|
|
* than a more direct method, but this is not a highly performance-cri- |
|
650
|
|
|
* tical code path and readable code is more important here. |
|
651
|
|
|
* |
|
652
|
|
|
* If the target namespace doesn't allow subpages, moving with subpages |
|
653
|
|
|
* would mean that you couldn't move them back in one operation, which |
|
654
|
|
|
* is bad. |
|
655
|
|
|
* @todo FIXME: A specific error message should be given in this case. |
|
656
|
|
|
*/ |
|
657
|
|
|
|
|
658
|
|
|
// @todo FIXME: Use Title::moveSubpages() here |
|
659
|
|
|
$dbr = wfGetDB( DB_MASTER ); |
|
660
|
|
|
if ( $this->moveSubpages && ( |
|
661
|
|
|
MWNamespace::hasSubpages( $nt->getNamespace() ) || ( |
|
662
|
|
|
$this->moveTalk |
|
663
|
|
|
&& MWNamespace::hasSubpages( $nt->getTalkPage()->getNamespace() ) |
|
664
|
|
|
) |
|
665
|
|
|
) ) { |
|
666
|
|
|
$conds = [ |
|
667
|
|
|
'page_title' . $dbr->buildLike( $ot->getDBkey() . '/', $dbr->anyString() ) |
|
668
|
|
|
. ' OR page_title = ' . $dbr->addQuotes( $ot->getDBkey() ) |
|
669
|
|
|
]; |
|
670
|
|
|
$conds['page_namespace'] = []; |
|
671
|
|
|
if ( MWNamespace::hasSubpages( $nt->getNamespace() ) ) { |
|
672
|
|
|
$conds['page_namespace'][] = $ot->getNamespace(); |
|
673
|
|
|
} |
|
674
|
|
|
if ( $this->moveTalk && |
|
675
|
|
|
MWNamespace::hasSubpages( $nt->getTalkPage()->getNamespace() ) |
|
676
|
|
|
) { |
|
677
|
|
|
$conds['page_namespace'][] = $ot->getTalkPage()->getNamespace(); |
|
678
|
|
|
} |
|
679
|
|
|
} elseif ( $this->moveTalk ) { |
|
680
|
|
|
$conds = [ |
|
681
|
|
|
'page_namespace' => $ot->getTalkPage()->getNamespace(), |
|
682
|
|
|
'page_title' => $ot->getDBkey() |
|
683
|
|
|
]; |
|
684
|
|
|
} else { |
|
685
|
|
|
# Skip the query |
|
686
|
|
|
$conds = null; |
|
687
|
|
|
} |
|
688
|
|
|
|
|
689
|
|
|
$extraPages = []; |
|
690
|
|
|
if ( !is_null( $conds ) ) { |
|
691
|
|
|
$extraPages = TitleArray::newFromResult( |
|
692
|
|
|
$dbr->select( 'page', |
|
|
|
|
|
|
693
|
|
|
[ 'page_id', 'page_namespace', 'page_title' ], |
|
694
|
|
|
$conds, |
|
695
|
|
|
__METHOD__ |
|
696
|
|
|
) |
|
697
|
|
|
); |
|
698
|
|
|
} |
|
699
|
|
|
|
|
700
|
|
|
$extraOutput = []; |
|
701
|
|
|
$count = 1; |
|
702
|
|
|
foreach ( $extraPages as $oldSubpage ) { |
|
|
|
|
|
|
703
|
|
|
if ( $ot->equals( $oldSubpage ) || $nt->equals( $oldSubpage ) ) { |
|
704
|
|
|
# Already did this one. |
|
705
|
|
|
continue; |
|
706
|
|
|
} |
|
707
|
|
|
|
|
708
|
|
|
$newPageName = preg_replace( |
|
709
|
|
|
'#^' . preg_quote( $ot->getDBkey(), '#' ) . '#', |
|
710
|
|
|
StringUtils::escapeRegexReplacement( $nt->getDBkey() ), # bug 21234 |
|
711
|
|
|
$oldSubpage->getDBkey() |
|
712
|
|
|
); |
|
713
|
|
|
|
|
714
|
|
|
if ( $oldSubpage->isSubpage() && ( $ot->isTalkPage() xor $nt->isTalkPage() ) ) { |
|
715
|
|
|
// Moving a subpage from a subject namespace to a talk namespace or vice-versa |
|
716
|
|
|
$newNs = $nt->getNamespace(); |
|
717
|
|
|
} elseif ( $oldSubpage->isTalkPage() ) { |
|
718
|
|
|
$newNs = $nt->getTalkPage()->getNamespace(); |
|
719
|
|
|
} else { |
|
720
|
|
|
$newNs = $nt->getSubjectPage()->getNamespace(); |
|
721
|
|
|
} |
|
722
|
|
|
|
|
723
|
|
|
# Bug 14385: we need makeTitleSafe because the new page names may |
|
724
|
|
|
# be longer than 255 characters. |
|
725
|
|
|
$newSubpage = Title::makeTitleSafe( $newNs, $newPageName ); |
|
726
|
|
|
if ( !$newSubpage ) { |
|
727
|
|
|
$oldLink = $linkRenderer->makeKnownLink( $oldSubpage ); |
|
728
|
|
|
$extraOutput[] = $this->msg( 'movepage-page-unmoved' )->rawParams( $oldLink ) |
|
729
|
|
|
->params( Title::makeName( $newNs, $newPageName ) )->escaped(); |
|
730
|
|
|
continue; |
|
731
|
|
|
} |
|
732
|
|
|
|
|
733
|
|
|
# This was copy-pasted from Renameuser, bleh. |
|
734
|
|
|
if ( $newSubpage->exists() && !$oldSubpage->isValidMoveTarget( $newSubpage ) ) { |
|
735
|
|
|
$link = $linkRenderer->makeKnownLink( $newSubpage ); |
|
736
|
|
|
$extraOutput[] = $this->msg( 'movepage-page-exists' )->rawParams( $link )->escaped(); |
|
737
|
|
|
} else { |
|
738
|
|
|
$success = $oldSubpage->moveTo( $newSubpage, true, $this->reason, $createRedirect ); |
|
739
|
|
|
|
|
740
|
|
|
if ( $success === true ) { |
|
741
|
|
|
if ( $this->fixRedirects ) { |
|
742
|
|
|
DoubleRedirectJob::fixRedirects( 'move', $oldSubpage, $newSubpage ); |
|
743
|
|
|
} |
|
744
|
|
|
$oldLink = $linkRenderer->makeLink( |
|
745
|
|
|
$oldSubpage, |
|
746
|
|
|
null, |
|
747
|
|
|
[], |
|
748
|
|
|
[ 'redirect' => 'no' ] |
|
749
|
|
|
); |
|
750
|
|
|
|
|
751
|
|
|
$newLink = $linkRenderer->makeKnownLink( $newSubpage ); |
|
752
|
|
|
$extraOutput[] = $this->msg( 'movepage-page-moved' ) |
|
753
|
|
|
->rawParams( $oldLink, $newLink )->escaped(); |
|
754
|
|
|
++$count; |
|
755
|
|
|
|
|
756
|
|
|
$maximumMovedPages = $this->getConfig()->get( 'MaximumMovedPages' ); |
|
757
|
|
|
if ( $count >= $maximumMovedPages ) { |
|
758
|
|
|
$extraOutput[] = $this->msg( 'movepage-max-pages' ) |
|
759
|
|
|
->numParams( $maximumMovedPages )->escaped(); |
|
760
|
|
|
break; |
|
761
|
|
|
} |
|
762
|
|
|
} else { |
|
763
|
|
|
$oldLink = $linkRenderer->makeKnownLink( $oldSubpage ); |
|
764
|
|
|
$newLink = $linkRenderer->makeLink( $newSubpage ); |
|
765
|
|
|
$extraOutput[] = $this->msg( 'movepage-page-unmoved' ) |
|
766
|
|
|
->rawParams( $oldLink, $newLink )->escaped(); |
|
767
|
|
|
} |
|
768
|
|
|
} |
|
769
|
|
|
} |
|
770
|
|
|
|
|
771
|
|
|
if ( $extraOutput !== [] ) { |
|
772
|
|
|
$out->addHTML( "<ul>\n<li>" . implode( "</li>\n<li>", $extraOutput ) . "</li>\n</ul>" ); |
|
773
|
|
|
} |
|
774
|
|
|
|
|
775
|
|
|
# Deal with watches (we don't watch subpages) |
|
776
|
|
|
WatchAction::doWatchOrUnwatch( $this->watch, $ot, $user ); |
|
777
|
|
|
WatchAction::doWatchOrUnwatch( $this->watch, $nt, $user ); |
|
778
|
|
|
} |
|
779
|
|
|
|
|
780
|
|
|
function showLogFragment( $title ) { |
|
781
|
|
|
$moveLogPage = new LogPage( 'move' ); |
|
782
|
|
|
$out = $this->getOutput(); |
|
783
|
|
|
$out->addHTML( Xml::element( 'h2', null, $moveLogPage->getName()->text() ) ); |
|
784
|
|
|
LogEventsList::showLogExtract( $out, 'move', $title ); |
|
785
|
|
|
} |
|
786
|
|
|
|
|
787
|
|
|
function showSubpages( $title ) { |
|
788
|
|
|
if ( !MWNamespace::hasSubpages( $title->getNamespace() ) ) { |
|
789
|
|
|
return; |
|
790
|
|
|
} |
|
791
|
|
|
|
|
792
|
|
|
$subpages = $title->getSubpages(); |
|
793
|
|
|
$count = $subpages instanceof TitleArray ? $subpages->count() : 0; |
|
794
|
|
|
|
|
795
|
|
|
$out = $this->getOutput(); |
|
796
|
|
|
$out->wrapWikiMsg( '== $1 ==', [ 'movesubpage', $count ] ); |
|
797
|
|
|
|
|
798
|
|
|
# No subpages. |
|
799
|
|
|
if ( $count == 0 ) { |
|
800
|
|
|
$out->addWikiMsg( 'movenosubpage' ); |
|
801
|
|
|
|
|
802
|
|
|
return; |
|
803
|
|
|
} |
|
804
|
|
|
|
|
805
|
|
|
$out->addWikiMsg( 'movesubpagetext', $this->getLanguage()->formatNum( $count ) ); |
|
806
|
|
|
$out->addHTML( "<ul>\n" ); |
|
807
|
|
|
|
|
808
|
|
|
$linkRenderer = $this->getLinkRenderer(); |
|
809
|
|
|
foreach ( $subpages as $subpage ) { |
|
810
|
|
|
$link = $linkRenderer->makeLink( $subpage ); |
|
811
|
|
|
$out->addHTML( "<li>$link</li>\n" ); |
|
812
|
|
|
} |
|
813
|
|
|
$out->addHTML( "</ul>\n" ); |
|
814
|
|
|
} |
|
815
|
|
|
|
|
816
|
|
|
/** |
|
817
|
|
|
* Return an array of subpages beginning with $search that this special page will accept. |
|
818
|
|
|
* |
|
819
|
|
|
* @param string $search Prefix to search for |
|
820
|
|
|
* @param int $limit Maximum number of results to return (usually 10) |
|
821
|
|
|
* @param int $offset Number of results to skip (usually 0) |
|
822
|
|
|
* @return string[] Matching subpages |
|
823
|
|
|
*/ |
|
824
|
|
|
public function prefixSearchSubpages( $search, $limit, $offset ) { |
|
825
|
|
|
return $this->prefixSearchString( $search, $limit, $offset ); |
|
826
|
|
|
} |
|
827
|
|
|
|
|
828
|
|
|
protected function getGroupName() { |
|
829
|
|
|
return 'pagetools'; |
|
830
|
|
|
} |
|
831
|
|
|
} |
|
832
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.