r105338 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105337‎ | r105338 | r105339 >
Date:19:32, 6 December 2011
Author:brion
Status:ok
Tags:
Comment:
Revert r104353, r104354, r104356, r104358, r104383: changes to pagers breaking existing links as noted in CR.
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/HTMLForm.php (modified) (history)
  • /trunk/phase3/includes/Pager.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialActiveusers.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialAllmessages.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialBlockList.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialCategories.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialListfiles.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialListusers.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialNewimages.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialProtectedtitles.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/HTMLForm.php
@@ -72,8 +72,6 @@
7373 'submit' => 'HTMLSubmitField',
7474 'hidden' => 'HTMLHiddenField',
7575 'edittools' => 'HTMLEditTools',
76 - 'namespaces' => 'HTMLNamespacesField',
77 - 'restrictionlevels' => 'HTMLRestrictionLevelsField',
7876
7977 # HTMLTextField will output the correct type="" attribute automagically.
8078 # There are about four zillion other HTML5 input types, like url, but
@@ -847,25 +845,6 @@
848846 public function getLegend( $key ) {
849847 return wfMsg( "{$this->mMessagePrefix}-$key" );
850848 }
851 -
852 - /**
853 - * Returns an array of fields in the form
854 - *
855 - * @return HTMLFormField[]
856 - */
857 - public function getFlatFields() {
858 - return $this->mFlatFields;
859 - }
860 -
861 - /**
862 - * Returns a value of a field
863 - *
864 - * @param $field string Field name
865 - * @return mixed
866 - */
867 - public function getVal( $field ) {
868 - return $this->mFieldData[$field];
869 - }
870849 }
871850
872851 /**
@@ -1092,15 +1071,6 @@
10931072 return $html;
10941073 }
10951074
1096 - /**
1097 - * Returns the HTML name of the Field
1098 - *
1099 - * @return string
1100 - */
1101 - public function getName() {
1102 - return $this->mName;
1103 - }
1104 -
11051075 function getLabel() {
11061076 return $this->mLabel;
11071077 }
@@ -2016,84 +1986,3 @@
20171987 . "</div></td></tr>\n";
20181988 }
20191989 }
2020 -
2021 -/**
2022 - * Dropdown for namespaces
2023 - */
2024 -class HTMLNamespacesField extends HTMLSelectField {
2025 - function __construct( $params ) {
2026 - global $wgContLang;
2027 - parent::__construct( $params );
2028 -
2029 - $namespaces = $wgContLang->getFormattedNamespaces();
2030 -
2031 - $options = array();
2032 - $options[ wfMessage( 'namespacesall' )->escaped() ] = ''; // TODO: Make an option
2033 -
2034 - foreach ( $namespaces as $index => $name ) {
2035 - // Don't include things like SpecialPages
2036 - if ( $index < NS_MAIN ) {
2037 - continue;
2038 - }
2039 -
2040 - if ( $index === 0 ) {
2041 - $name = wfMessage( 'blanknamespace' )->escaped();
2042 - }
2043 -
2044 - $options[$name] = $index;
2045 - }
2046 -
2047 - $this->mParams['options'] = $options;
2048 - }
2049 -}
2050 -
2051 -/**
2052 - * Dropdown for protection levels
2053 - */
2054 -class HTMLRestrictionLevelsField extends HTMLSelectField {
2055 -
2056 - /**
2057 - * Should this field be displayed? If it hits a condition where it should
2058 - * be hidden, set this to false.
2059 - *
2060 - * @var bool
2061 - */
2062 - protected $enabled = true;
2063 -
2064 - function __construct( $params ) {
2065 - global $wgRestrictionLevels;
2066 - parent::__construct( $params );
2067 -
2068 - $options = array( wfMsg('restriction-level-all') => 0 ); // Temporary array
2069 -
2070 - // First pass to load the level names
2071 - foreach( $wgRestrictionLevels as $type ) {
2072 - if ( $type != '' && $type != '*' ) {
2073 - $text = wfMsg("restriction-level-$type");
2074 - $options[$text] = $type;
2075 - }
2076 - }
2077 -
2078 - // Is there only one level (aside from "all")?
2079 - if( count($options) <= 2 ) {
2080 - $this->enabled = false;
2081 - return;
2082 - }
2083 -
2084 - $this->mParams['options'] = $options;
2085 - }
2086 -
2087 - /**
2088 - * Returns false where
2089 - *
2090 - * @param $value
2091 - * @return String
2092 - */
2093 - function getTableRow( $value ) {
2094 - if ( $this->enabled ) {
2095 - return parent::getTableRow( $value );
2096 - }
2097 -
2098 - return '';
2099 - }
2100 -}
\ No newline at end of file
Index: trunk/phase3/includes/AutoLoader.php
@@ -104,7 +104,6 @@
105105 'HTMLHiddenField' => 'includes/HTMLForm.php',
106106 'HTMLInfoField' => 'includes/HTMLForm.php',
107107 'HTMLIntField' => 'includes/HTMLForm.php',
108 - 'HTMLItemsPerPageField' => 'includes/Pager.php',
109108 'HTMLMultiSelectField' => 'includes/HTMLForm.php',
110109 'HTMLRadioField' => 'includes/HTMLForm.php',
111110 'HTMLSelectAndOtherField' => 'includes/HTMLForm.php',
@@ -747,6 +746,7 @@
748747 'EmailInvalidation' => 'includes/specials/SpecialConfirmemail.php',
749748 'FewestrevisionsPage' => 'includes/specials/SpecialFewestrevisions.php',
750749 'FileDuplicateSearchPage' => 'includes/specials/SpecialFileDuplicateSearch.php',
 750+ 'HTMLBlockedUsersItemSelect' => 'includes/specials/SpecialBlockList.php',
751751 'ImportReporter' => 'includes/specials/SpecialImport.php',
752752 'IPBlockForm' => 'includes/specials/SpecialBlock.php',
753753 'LinkSearchPage' => 'includes/specials/SpecialLinkSearch.php',
Index: trunk/phase3/includes/specials/SpecialAllmessages.php
@@ -62,18 +62,18 @@
6363
6464 $out->addModuleStyles( 'mediawiki.special' );
6565
66 - $this->filter = $request->getVal( 'wpFilter', 'all' );
67 - $this->prefix = $request->getVal( 'wpPrefix', '' );
 66+ $this->filter = $request->getVal( 'filter', 'all' );
 67+ $this->prefix = $request->getVal( 'prefix', '' );
6868
6969 $this->table = new AllmessagesTablePager(
7070 $this,
7171 array(),
72 - wfGetLangObj( $request->getVal( 'wpLanguage', $par ) )
 72+ wfGetLangObj( $request->getVal( 'lang', $par ) )
7373 );
7474
7575 $this->langcode = $this->table->lang->getCode();
7676
77 - $out->addHTML( $this->table->buildHTMLForm() .
 77+ $out->addHTML( $this->table->buildForm() .
7878 $this->table->getNavigationBar() .
7979 $this->table->getBody() .
8080 $this->table->getNavigationBar() );
@@ -120,14 +120,14 @@
121121
122122 $request = $this->getRequest();
123123
124 - if( $request->getVal( 'wpFilter', 'all' ) === 'all' ){
 124+ if( $request->getVal( 'filter', 'all' ) === 'all' ){
125125 $this->custom = null; // So won't match in either case
126126 } else {
127 - $this->custom = ($request->getVal( 'wpFilter' ) == 'unmodified');
 127+ $this->custom = ($request->getVal( 'filter' ) == 'unmodified');
128128 }
129129
130 - $prefix = $this->getLanguage()->ucfirst( $request->getVal( 'wpPrefix', '' ) );
131 - $prefix = $prefix != '' ? Title::makeTitleSafe( NS_MEDIAWIKI, $request->getVal( 'wpPrefix', null ) ) : null;
 130+ $prefix = $this->getLanguage()->ucfirst( $request->getVal( 'prefix', '' ) );
 131+ $prefix = $prefix != '' ? Title::makeTitleSafe( NS_MEDIAWIKI, $request->getVal( 'prefix', null ) ) : null;
132132 if( $prefix !== null ){
133133 $this->displayPrefix = $prefix->getDBkey();
134134 $this->prefix = '/^' . preg_quote( $this->displayPrefix ) . '/i';
@@ -145,50 +145,85 @@
146146 }
147147 }
148148
149 - protected function getHTMLFormFields() {
150 - $f = array(
151 - 'Prefix' => array(
152 - 'type' => 'text',
153 - 'label-message' => 'allmessages-prefix',
154 - 'size' => 20,
155 - ),
156 - 'Filter' => array(
157 - 'type' => 'radio',
158 - 'label-message' => 'allmessages-filter',
159 - 'options' => array(
160 - $this->msg( 'allmessages-filter-unmodified' )->text() => 'unmodified',
161 - $this->msg( 'allmessages-filter-all' )->text() => 'all',
162 - $this->msg( 'allmessages-filter-modified' )->text() => 'modified',
163 - ),
164 - 'flatlist' => true,
165 - ),
166 - 'Language' => array(
167 - 'type' => 'select',
168 - 'label-message' => 'allmessages-language',
169 - 'options' => array(), // This is filled in below
170 - 'default' => $this->langcode,
171 - ),
172 - 'Limit' => $this->getHTMLFormLimitSelect(),
173 - );
 149+ function buildForm() {
 150+ global $wgScript;
174151
175152 $languages = Language::getLanguageNames( false );
176153 ksort( $languages );
177154
178 - foreach( $languages as $code => $name ) {
179 - $f['Language']['options'][ "$code - $name" ] = $code;
 155+ $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-allmessages-form' ) ) .
 156+ Xml::fieldset( $this->msg( 'allmessages-filter-legend' )->text() ) .
 157+ Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
 158+ Xml::openElement( 'table', array( 'class' => 'mw-allmessages-table' ) ) . "\n" .
 159+ '<tr>
 160+ <td class="mw-label">' .
 161+ Xml::label( $this->msg( 'allmessages-prefix' )->text(), 'mw-allmessages-form-prefix' ) .
 162+ "</td>\n
 163+ <td class=\"mw-input\">" .
 164+ Xml::input( 'prefix', 20, str_replace( '_', ' ', $this->displayPrefix ), array( 'id' => 'mw-allmessages-form-prefix' ) ) .
 165+ "</td>\n
 166+ </tr>
 167+ <tr>\n
 168+ <td class='mw-label'>" .
 169+ $this->msg( 'allmessages-filter' )->escaped() .
 170+ "</td>\n
 171+ <td class='mw-input'>" .
 172+ Xml::radioLabel( $this->msg( 'allmessages-filter-unmodified' )->text(),
 173+ 'filter',
 174+ 'unmodified',
 175+ 'mw-allmessages-form-filter-unmodified',
 176+ ( $this->filter == 'unmodified' )
 177+ ) .
 178+ Xml::radioLabel( $this->msg( 'allmessages-filter-all' )->text(),
 179+ 'filter',
 180+ 'all',
 181+ 'mw-allmessages-form-filter-all',
 182+ ( $this->filter == 'all' )
 183+ ) .
 184+ Xml::radioLabel( $this->msg( 'allmessages-filter-modified' )->text(),
 185+ 'filter',
 186+ 'modified',
 187+ 'mw-allmessages-form-filter-modified',
 188+ ( $this->filter == 'modified' )
 189+ ) .
 190+ "</td>\n
 191+ </tr>
 192+ <tr>\n
 193+ <td class=\"mw-label\">" .
 194+ Xml::label( $this->msg( 'allmessages-language' )->text(), 'mw-allmessages-form-lang' ) .
 195+ "</td>\n
 196+ <td class=\"mw-input\">" .
 197+ Xml::openElement( 'select', array( 'id' => 'mw-allmessages-form-lang', 'name' => 'lang' ) );
 198+
 199+ foreach( $languages as $lang => $name ) {
 200+ $selected = $lang == $this->langcode;
 201+ $out .= Xml::option( $lang . ' - ' . $name, $lang, $selected ) . "\n";
180202 }
 203+ $out .= Xml::closeElement( 'select' ) .
 204+ "</td>\n
 205+ </tr>" .
181206
182 - return $f;
183 - }
 207+ '<tr>
 208+ <td class="mw-label">' .
 209+ Xml::label( $this->msg( 'table_pager_limit_label' )->text(), 'mw-table_pager_limit_label' ) .
 210+ '</td>
 211+ <td class="mw-input">' .
 212+ $this->getLimitSelect() .
 213+ '</td>
 214+ <tr>
 215+ <td></td>
 216+ <td>' .
 217+ Xml::submitButton( $this->msg( 'allmessages-filter-submit' )->text() ) .
 218+ "</td>\n
 219+ </tr>" .
184220
185 - protected function getHTMLFormLegend() {
186 - return 'allmessages-filter-legend';
 221+ Xml::closeElement( 'table' ) .
 222+ $this->getHiddenFields( array( 'title', 'prefix', 'filter', 'lang', 'limit' ) ) .
 223+ Xml::closeElement( 'fieldset' ) .
 224+ Xml::closeElement( 'form' );
 225+ return $out;
187226 }
188227
189 - protected function getHTMLFormSubmit() {
190 - return 'allmessages-filter-submit';
191 - }
192 -
193228 function getAllMessages( $descending ) {
194229 wfProfileIn( __METHOD__ );
195230 $messageNames = Language::getLocalisationCache()->getSubitemList( 'en', 'messages' );
Index: trunk/phase3/includes/specials/SpecialCategories.php
@@ -35,7 +35,7 @@
3636 $this->outputHeader();
3737 $this->getOutput()->allowClickjacking();
3838
39 - $from = $this->getRequest()->getText( 'wpFrom', $par );
 39+ $from = $this->getRequest()->getText( 'from', $par );
4040
4141 $cap = new CategoryPager( $this->getContext(), $from );
4242 $cap->doQuery();
@@ -43,7 +43,7 @@
4444 $this->getOutput()->addHTML(
4545 Html::openElement( 'div', array( 'class' => 'mw-spcontent' ) ) .
4646 $this->msg( 'categoriespagetext', $cap->getNumRows() )->parseAsBlock() .
47 - $cap->buildHTMLForm() .
 47+ $cap->getStartForm( $from ) .
4848 $cap->getNavigationBar() .
4949 '<ul>' . $cap->getBody() . '</ul>' .
5050 $cap->getNavigationBar() .
@@ -118,21 +118,16 @@
119119 return Xml::tags( 'li', null, $this->getLanguage()->specialList( $titleText, $count ) ) . "\n";
120120 }
121121
122 - protected function getHTMLFormFields() {
123 - return array(
124 - 'From' => array(
125 - 'type' => 'text',
126 - 'label-message' => 'categoriesfrom',
127 - 'size' => '20',
128 - ),
129 - );
130 - }
 122+ public function getStartForm( $from ) {
 123+ global $wgScript;
131124
132 - protected function getHTMLFormLegend() {
133 - return 'categories';
 125+ return
 126+ Xml::tags( 'form', array( 'method' => 'get', 'action' => $wgScript ),
 127+ Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
 128+ Xml::fieldset( $this->msg( 'categories' )->text(),
 129+ Xml::inputLabel( $this->msg( 'categoriesfrom' )->text(),
 130+ 'from', 'from', 20, $from ) .
 131+ ' ' .
 132+ Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) ) );
134133 }
135 -
136 - protected function getHTMLFormSubmit() {
137 - return 'allpagessubmit';
138 - }
139134 }
Index: trunk/phase3/includes/specials/SpecialBlockList.php
@@ -43,13 +43,13 @@
4444 $this->setHeaders();
4545 $this->outputHeader();
4646 $out = $this->getOutput();
 47+ $lang = $this->getLanguage();
4748 $out->setPageTitle( $this->msg( 'ipblocklist' ) );
4849 $out->addModuleStyles( 'mediawiki.special' );
4950
5051 $request = $this->getRequest();
5152 $par = $request->getVal( 'ip', $par );
5253 $this->target = trim( $request->getVal( 'wpTarget', $par ) );
53 - $request->setVal( 'wpTarget', $this->target );
5454
5555 $this->options = $request->getArray( 'wpOptions', array() );
5656
@@ -62,6 +62,46 @@
6363 return;
6464 }
6565
 66+ # Just show the block list
 67+ $fields = array(
 68+ 'Target' => array(
 69+ 'type' => 'text',
 70+ 'label-message' => 'ipadressorusername',
 71+ 'tabindex' => '1',
 72+ 'size' => '45',
 73+ 'default' => $this->target,
 74+ ),
 75+ 'Options' => array(
 76+ 'type' => 'multiselect',
 77+ 'options' => array(
 78+ wfMsg( 'blocklist-userblocks' ) => 'userblocks',
 79+ wfMsg( 'blocklist-tempblocks' ) => 'tempblocks',
 80+ wfMsg( 'blocklist-addressblocks' ) => 'addressblocks',
 81+ wfMsg( 'blocklist-rangeblocks' ) => 'rangeblocks',
 82+ ),
 83+ 'flatlist' => true,
 84+ ),
 85+ 'Limit' => array(
 86+ 'class' => 'HTMLBlockedUsersItemSelect',
 87+ 'label-message' => 'table_pager_limit_label',
 88+ 'options' => array(
 89+ $lang->formatNum( 20 ) => 20,
 90+ $lang->formatNum( 50 ) => 50,
 91+ $lang->formatNum( 100 ) => 100,
 92+ $lang->formatNum( 250 ) => 250,
 93+ $lang->formatNum( 500 ) => 500,
 94+ ),
 95+ 'name' => 'limit',
 96+ 'default' => 50,
 97+ ),
 98+ );
 99+ $form = new HTMLForm( $fields, $this->getContext() );
 100+ $form->setMethod( 'get' );
 101+ $form->setWrapperLegend( wfMsg( 'ipblocklist-legend' ) );
 102+ $form->setSubmitText( wfMsg( 'ipblocklist-submit' ) );
 103+ $form->prepareForm();
 104+
 105+ $form->displayForm( '' );
66106 $this->showList();
67107 }
68108
@@ -136,7 +176,6 @@
137177 }
138178
139179 $pager = new BlockListPager( $this, $conds );
140 - $out->addHTML( $pager->buildHTMLForm() );
141180 if ( $pager->getNumRows() ) {
142181 $out->addHTML(
143182 $pager->getNavigationBar() .
@@ -360,37 +399,6 @@
361400 return $info;
362401 }
363402
364 - protected function getHTMLFormFields() {
365 - return array(
366 - 'Target' => array(
367 - 'type' => 'text',
368 - 'label-message' => 'ipadressorusername',
369 - 'tabindex' => '1',
370 - 'size' => '45',
371 - //'default' => $this->target,
372 - ),
373 - 'Options' => array(
374 - 'type' => 'multiselect',
375 - 'options' => array(
376 - wfMsg( 'blocklist-userblocks' ) => 'userblocks',
377 - wfMsg( 'blocklist-tempblocks' ) => 'tempblocks',
378 - wfMsg( 'blocklist-addressblocks' ) => 'addressblocks',
379 - wfMsg( 'blocklist-rangeblocks' ) => 'rangeblocks',
380 - ),
381 - 'flatlist' => true,
382 - ),
383 - 'Limit' => $this->getHTMLFormLimitSelect(),
384 - );
385 - }
386 -
387 - protected function getHTMLFormSubmit() {
388 - return 'ipblocklist-submit';
389 - }
390 -
391 - protected function getHTMLFormLegend() {
392 - return 'ipblocklist-legend';
393 - }
394 -
395403 public function getTableClass(){
396404 return 'TablePager mw-blocklist';
397405 }
@@ -439,4 +447,33 @@
440448 $lb->execute();
441449 wfProfileOut( __METHOD__ );
442450 }
443 -}
\ No newline at end of file
 451+}
 452+
 453+/**
 454+ * Items per page dropdown. Essentially a crap workaround for bug 32603.
 455+ *
 456+ * @todo Do not release 1.19 with this.
 457+ */
 458+class HTMLBlockedUsersItemSelect extends HTMLSelectField {
 459+ /**
 460+ * Basically don't do any validation. If it's a number that's fine. Also,
 461+ * add it to the list if it's not there already
 462+ *
 463+ * @param $value
 464+ * @param $alldata
 465+ * @return bool
 466+ */
 467+ function validate( $value, $alldata ) {
 468+ if ( $value == '' ) {
 469+ return true;
 470+ }
 471+
 472+ if ( !in_array( $value, $this->mParams['options'] ) ) {
 473+ $this->mParams['options'][ $this->mParent->getLanguage()->formatNum( $value ) ] = intval($value);
 474+ asort( $this->mParams['options'] );
 475+ }
 476+
 477+ return true;
 478+ }
 479+
 480+}
Index: trunk/phase3/includes/specials/SpecialListfiles.php
@@ -35,8 +35,8 @@
3636 $userName = $par;
3737 $search = '';
3838 } else {
39 - $userName = $this->getRequest()->getText( 'wpUsername', $par );
40 - $search = $this->getRequest()->getText( 'wpSearch', '' );
 39+ $userName = $this->getRequest()->getText( 'user', $par );
 40+ $search = $this->getRequest()->getText( 'ilsearch', '' );
4141 }
4242
4343 $pager = new ImageListPager( $this->getContext(), $userName, $search, $this->including() );
@@ -44,7 +44,7 @@
4545 if ( $this->including() ) {
4646 $html = $pager->getBody();
4747 } else {
48 - $form = $pager->buildHTMLForm();
 48+ $form = $pager->getForm();
4949 $body = $pager->getBody();
5050 $nav = $pager->getNavigationBar();
5151 $html = "$form<br />\n$body<br />\n$nav";
@@ -234,37 +234,32 @@
235235 }
236236 }
237237
238 - protected function getHTMLFormFields() {
239 - global $wgMiserMode;
240 - $f = array(
241 - 'Limit' => $this->getHTMLFormLimitSelect(),
242 - );
243 -
 238+ function getForm() {
 239+ global $wgScript, $wgMiserMode;
 240+ $inputForm = array();
 241+ $inputForm['table_pager_limit_label'] = $this->getLimitSelect();
244242 if ( !$wgMiserMode ) {
245 - $f['Search'] = array(
246 - 'type' => 'text',
247 - 'label-message' => 'listfiles_search_for',
248 - 'maxlength' => 255,
249 - );
 243+ $inputForm['listfiles_search_for'] = Html::input( 'ilsearch', $this->mSearch, 'text',
 244+ array(
 245+ 'size' => '40',
 246+ 'maxlength' => '255',
 247+ 'id' => 'mw-ilsearch',
 248+ ) );
250249 }
251 -
252 - $f['Username'] = array(
253 - 'type' => 'text',
254 - 'label-message' => 'username',
255 - 'maxlength' => 255,
256 - );
257 -
258 - return $f;
 250+ $inputForm['username'] = Html::input( 'user', $this->mUserName, 'text', array(
 251+ 'size' => '40',
 252+ 'maxlength' => '255',
 253+ 'id' => 'mw-listfiles-user',
 254+ ) );
 255+ return Html::openElement( 'form',
 256+ array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listfiles-form' ) ) .
 257+ Xml::fieldset( wfMsg( 'listfiles' ) ) .
 258+ Xml::buildForm( $inputForm, 'table_pager_limit_submit' ) .
 259+ $this->getHiddenFields( array( 'limit', 'ilsearch', 'user' ) ) .
 260+ Html::closeElement( 'fieldset' ) .
 261+ Html::closeElement( 'form' ) . "\n";
259262 }
260263
261 - protected function getHTMLFormLegend() {
262 - return 'listfiles';
263 - }
264 -
265 - protected function getHTMLFormSubmit() {
266 - return 'table_pager_limit_submit';
267 - }
268 -
269264 function getTableClass() {
270265 return 'listfiles ' . parent::getTableClass();
271266 }
Index: trunk/phase3/includes/specials/SpecialProtectedtitles.php
@@ -28,6 +28,9 @@
2929 */
3030 class SpecialProtectedtitles extends SpecialPage {
3131
 32+ protected $IdLevel = 'level';
 33+ protected $IdType = 'type';
 34+
3235 public function __construct() {
3336 parent::__construct( 'Protectedtitles' );
3437 }
@@ -41,9 +44,17 @@
4245 Title::purgeExpiredRestrictions();
4346 }
4447
45 - $pager = new ProtectedTitlesPager( $this );
46 - $this->getOutput()->addHTML( $pager->buildHTMLForm() );
 48+ $request = $this->getRequest();
 49+ $type = $request->getVal( $this->IdType );
 50+ $level = $request->getVal( $this->IdLevel );
 51+ $sizetype = $request->getVal( 'sizetype' );
 52+ $size = $request->getIntOrNull( 'size' );
 53+ $NS = $request->getIntOrNull( 'namespace' );
4754
 55+ $pager = new ProtectedTitlesPager( $this, array(), $type, $level, $NS, $sizetype, $size );
 56+
 57+ $this->getOutput()->addHTML( $this->showOptions( $NS, $type, $level ) );
 58+
4859 if ( $pager->getNumRows() ) {
4960 $s = $pager->getNavigationBar();
5061 $s .= "<ul>" .
@@ -59,7 +70,6 @@
6071 /**
6172 * Callback function to output a restriction
6273 *
63 - * @param $row
6474 * @return string
6575 */
6676 function formatRow( $row ) {
@@ -97,30 +107,89 @@
98108
99109 return '<li>' . $lang->specialList( $link, implode( $description_items, ', ' ) ) . "</li>\n";
100110 }
101 -}
102111
103 -/**
104 - * @todo document
105 - * @ingroup Pager
106 - */
107 -class ProtectedTitlesPager extends AlphabeticPager {
108112 /**
109 - * @var SpecialProtectedtitles
 113+ * @param $namespace Integer:
 114+ * @param $type string
 115+ * @param $level string
 116+ * @private
110117 */
111 - public $mForm;
 118+ function showOptions( $namespace, $type='edit', $level ) {
 119+ global $wgScript;
 120+ $action = htmlspecialchars( $wgScript );
 121+ $title = $this->getTitle();
 122+ $special = htmlspecialchars( $title->getPrefixedDBkey() );
 123+ return "<form action=\"$action\" method=\"get\">\n" .
 124+ '<fieldset>' .
 125+ Xml::element( 'legend', array(), wfMsg( 'protectedtitles' ) ) .
 126+ Html::hidden( 'title', $special ) . "&#160;\n" .
 127+ $this->getNamespaceMenu( $namespace ) . "&#160;\n" .
 128+ $this->getLevelMenu( $level ) . "&#160;\n" .
 129+ "&#160;" . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
 130+ "</fieldset></form>";
 131+ }
112132
113133 /**
114 - * @var array
 134+ * Prepare the namespace filter drop-down; standard namespace
 135+ * selector, sans the MediaWiki namespace
 136+ *
 137+ * @param $namespace Mixed: pre-select namespace
 138+ * @return string
115139 */
116 - public $mConds;
 140+ function getNamespaceMenu( $namespace = null ) {
 141+ return Xml::label( wfMsg( 'namespace' ), 'namespace' )
 142+ . '&#160;'
 143+ . Xml::namespaceSelector( $namespace, '' );
 144+ }
117145
118146 /**
119 - * @param $form SpecialProtectedtitles
120 - * @param $conds array
 147+ * @return string Formatted HTML
 148+ * @private
121149 */
122 - function __construct( $form, $conds = array() ) {
 150+ function getLevelMenu( $pr_level ) {
 151+ global $wgRestrictionLevels;
 152+
 153+ $m = array( wfMsg('restriction-level-all') => 0 ); // Temporary array
 154+ $options = array();
 155+
 156+ // First pass to load the log names
 157+ foreach( $wgRestrictionLevels as $type ) {
 158+ if ( $type !='' && $type !='*') {
 159+ $text = wfMsg("restriction-level-$type");
 160+ $m[$text] = $type;
 161+ }
 162+ }
 163+ // Is there only one level (aside from "all")?
 164+ if( count($m) <= 2 ) {
 165+ return '';
 166+ }
 167+ // Third pass generates sorted XHTML content
 168+ foreach( $m as $text => $type ) {
 169+ $selected = ($type == $pr_level );
 170+ $options[] = Xml::option( $text, $type, $selected );
 171+ }
 172+
 173+ return
 174+ Xml::label( wfMsg('restriction-level') , $this->IdLevel ) . '&#160;' .
 175+ Xml::tags( 'select',
 176+ array( 'id' => $this->IdLevel, 'name' => $this->IdLevel ),
 177+ implode( "\n", $options ) );
 178+ }
 179+}
 180+
 181+/**
 182+ * @todo document
 183+ * @ingroup Pager
 184+ */
 185+class ProtectedTitlesPager extends AlphabeticPager {
 186+ public $mForm, $mConds;
 187+
 188+ function __construct( $form, $conds = array(), $type, $level, $namespace, $sizetype='', $size=0 ) {
123189 $this->mForm = $form;
124190 $this->mConds = $conds;
 191+ $this->level = $level;
 192+ $this->namespace = $namespace;
 193+ $this->size = intval($size);
125194 parent::__construct( $form->getContext() );
126195 }
127196
@@ -156,14 +225,10 @@
157226 function getQueryInfo() {
158227 $conds = $this->mConds;
159228 $conds[] = 'pt_expiry>' . $this->mDb->addQuotes( $this->mDb->timestamp() );
160 -
161 - if ( $this->mHTMLForm->getVal( 'Level' ) ) {
162 - $conds['pt_create_perm'] = $this->mHTMLForm->getVal( 'Level' );
163 - }
164 - if ( $this->mHTMLForm->getVal( 'Namespace' ) !== '' ) {
165 - $conds['pt_namespace'] = $this->mHTMLForm->getVal( 'Namespace' );
166 - }
167 -
 229+ if( $this->level )
 230+ $conds['pt_create_perm'] = $this->level;
 231+ if( !is_null($this->namespace) )
 232+ $conds[] = 'pt_namespace=' . $this->mDb->addQuotes( $this->namespace );
168233 return array(
169234 'tables' => 'protected_titles',
170235 'fields' => 'pt_namespace,pt_title,pt_create_perm,pt_expiry,pt_timestamp',
@@ -174,28 +239,5 @@
175240 function getIndexField() {
176241 return 'pt_timestamp';
177242 }
178 -
179 - protected function getHTMLFormFields() {
180 - return array(
181 - 'Namespace' => array(
182 - 'type' => 'namespaces',
183 - 'label-message' => 'namespace',
184 - ),
185 - 'Level' => array(
186 - 'type' => 'restrictionlevels',
187 - 'label-message' => 'restriction-level',
188 - ),
189 - );
190 - }
191 -
192 - protected function getHTMLFormSubmit() {
193 - return 'allpagessubmit';
194 - }
195 -
196 - protected function getHTMLFormLegend() {
197 - return 'protectedtitles';
198 - }
199 -
200 -
201243 }
202244
Index: trunk/phase3/includes/specials/SpecialListusers.php
@@ -44,19 +44,19 @@
4545 $symsForAll = array( '*', 'user' );
4646 if ( $parms[0] != '' && ( in_array( $par, User::getAllGroups() ) || in_array( $par, $symsForAll ) ) ) {
4747 $this->requestedGroup = $par;
48 - $un = $request->getText( 'wpUsername' );
 48+ $un = $request->getText( 'username' );
4949 } elseif ( count( $parms ) == 2 ) {
5050 $this->requestedGroup = $parms[0];
5151 $un = $parms[1];
5252 } else {
53 - $this->requestedGroup = $request->getVal( 'wpGroup' );
54 - $un = ( $par != '' ) ? $par : $request->getText( 'wpUsername' );
 53+ $this->requestedGroup = $request->getVal( 'group' );
 54+ $un = ( $par != '' ) ? $par : $request->getText( 'username' );
5555 }
5656 if ( in_array( $this->requestedGroup, $symsForAll ) ) {
5757 $this->requestedGroup = '';
5858 }
59 - $this->editsOnly = $request->getBool( 'wpEditsOnly' );
60 - $this->creationSort = $request->getBool( 'wpCreationSort' );
 59+ $this->editsOnly = $request->getBool( 'editsOnly' );
 60+ $this->creationSort = $request->getBool( 'creationSort' );
6161
6262 $this->requestedUser = '';
6363 if ( $un != '' ) {
@@ -182,43 +182,41 @@
183183 return parent::getBody();
184184 }
185185
186 - protected function getHTMLFormFields() {
187 - $f = array(
188 - 'Username' => array(
189 - 'type' => 'text',
190 - 'label-message' => 'listusersfrom',
191 - 'size' => 30,
192 - ),
193 - 'Group' => array(
194 - 'type' => 'select',
195 - 'label-message' => 'group',
196 - 'options' => array(
197 - $this->msg( 'group-all' )->escaped() => '',
198 - ),
199 - ),
200 - 'EditsOnly' => array(
201 - 'type' => 'check',
202 - 'label-message' => 'listusers-editsonly',
203 - ),
204 - 'CreationSort' => array(
205 - 'type' => 'check',
206 - 'label-message' => 'listusers-creationsort',
207 - ),
208 - );
 186+ function getPageHeader( ) {
 187+ global $wgScript;
 188+ $self = $this->getTitle();
209189
210 - foreach( $this->getAllGroups() as $group => $groupText ) {
211 - $f['Group']['options'][$groupText] = $group;
212 - }
 190+ # Form tag
 191+ $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listusers-form' ) ) .
 192+ Xml::fieldset( wfMsg( 'listusers' ) ) .
 193+ Html::hidden( 'title', $self->getPrefixedDbKey() );
213194
214 - return $f;
215 - }
 195+ # Username field
 196+ $out .= Xml::label( wfMsg( 'listusersfrom' ), 'offset' ) . ' ' .
 197+ Xml::input( 'username', 20, $this->requestedUser, array( 'id' => 'offset' ) ) . ' ';
216198
217 - protected function getHTMLFormSubmit() {
218 - return 'allpagessubmit';
219 - }
 199+ # Group drop-down list
 200+ $out .= Xml::label( wfMsg( 'group' ), 'group' ) . ' ' .
 201+ Xml::openElement('select', array( 'name' => 'group', 'id' => 'group' ) ) .
 202+ Xml::option( wfMsg( 'group-all' ), '' );
 203+ foreach( $this->getAllGroups() as $group => $groupText )
 204+ $out .= Xml::option( $groupText, $group, $group == $this->requestedGroup );
 205+ $out .= Xml::closeElement( 'select' ) . '<br />';
 206+ $out .= Xml::checkLabel( wfMsg('listusers-editsonly'), 'editsOnly', 'editsOnly', $this->editsOnly );
 207+ $out .= '&#160;';
 208+ $out .= Xml::checkLabel( wfMsg('listusers-creationsort'), 'creationSort', 'creationSort', $this->creationSort );
 209+ $out .= '<br />';
220210
221 - protected function getHTMLFormLegend() {
222 - return 'listusers';
 211+ wfRunHooks( 'SpecialListusersHeaderForm', array( $this, &$out ) );
 212+
 213+ # Submit button and form bottom
 214+ $out .= Html::hidden( 'limit', $this->mLimit );
 215+ $out .= Xml::submitButton( wfMsg( 'allpagessubmit' ) );
 216+ wfRunHooks( 'SpecialListusersHeader', array( $this, &$out ) );
 217+ $out .= Xml::closeElement( 'fieldset' ) .
 218+ Xml::closeElement( 'form' );
 219+
 220+ return $out;
223221 }
224222
225223 /**
@@ -297,7 +295,7 @@
298296 # getBody() first to check, if empty
299297 $usersbody = $up->getBody();
300298
301 - $s = $up->buildHTMLForm();
 299+ $s = $up->getPageHeader();
302300 if( $usersbody ) {
303301 $s .= $up->getNavigationBar();
304302 $s .= Html::rawElement( 'ul', array(), $usersbody );
Index: trunk/phase3/includes/specials/SpecialActiveusers.php
@@ -53,7 +53,7 @@
5454 parent::__construct( $context );
5555
5656 $this->RCMaxAge = $wgActiveUserDays;
57 - $un = $this->getRequest()->getText( 'wpUsername', $par );
 57+ $un = $this->getRequest()->getText( 'username', $par );
5858 $this->requestedUser = '';
5959 if ( $un != '' ) {
6060 $username = Title::makeTitleSafe( NS_USER, $un );
@@ -68,16 +68,16 @@
6969 public function setupOptions() {
7070 $this->opts = new FormOptions();
7171
72 - $this->opts->add( 'wpHideBots', false, FormOptions::BOOL );
73 - $this->opts->add( 'wpHideSysops', false, FormOptions::BOOL );
 72+ $this->opts->add( 'hidebots', false, FormOptions::BOOL );
 73+ $this->opts->add( 'hidesysops', false, FormOptions::BOOL );
7474
7575 $this->opts->fetchValuesFromRequest( $this->getRequest() );
7676
7777 $this->groups = array();
78 - if ( $this->opts->getValue( 'wpHideBots' ) == 1 ) {
 78+ if ( $this->opts->getValue( 'hidebots' ) == 1 ) {
7979 $this->groups['bot'] = true;
8080 }
81 - if ( $this->opts->getValue( 'wpHideSysops' ) == 1 ) {
 81+ if ( $this->opts->getValue( 'hidesysops' ) == 1 ) {
8282 $this->groups['sysop'] = true;
8383 }
8484 }
@@ -143,32 +143,30 @@
144144 return Html::rawElement( 'li', array(), "{$item} [{$count}]{$blocked}" );
145145 }
146146
147 - protected function getHTMLFormFields() {
148 - $f = array(
149 - 'Username' => array(
150 - 'type' => 'text',
151 - 'label-message' => 'activeusers-from',
152 - 'size' => 30,
153 - ),
154 - 'HideBots' => array(
155 - 'type' => 'check',
156 - 'label-message' => 'activeusers-hidebots',
157 - ),
158 - 'HideSysops' => array(
159 - 'type' => 'check',
160 - 'label-message' => 'activeusers-hidesysops',
161 - ),
162 - );
 147+ function getPageHeader() {
 148+ global $wgScript;
163149
164 - return $f;
165 - }
 150+ $self = $this->getTitle();
 151+ $limit = $this->mLimit ? Html::hidden( 'limit', $this->mLimit ) : '';
166152
167 - protected function getHTMLFormLegend() {
168 - return 'activeusers';
169 - }
 153+ $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); # Form tag
 154+ $out .= Xml::fieldset( $this->msg( 'activeusers' )->text() ) . "\n";
 155+ $out .= Html::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n";
170156
171 - protected function getHTMLFormSubmit() {
172 - return 'allpagessubmit';
 157+ $out .= Xml::inputLabel( $this->msg( 'activeusers-from' )->text(),
 158+ 'username', 'offset', 20, $this->requestedUser ) . '<br />';# Username field
 159+
 160+ $out .= Xml::checkLabel( $this->msg( 'activeusers-hidebots' )->text(),
 161+ 'hidebots', 'hidebots', $this->opts->getValue( 'hidebots' ) );
 162+
 163+ $out .= Xml::checkLabel( $this->msg( 'activeusers-hidesysops' )->text(),
 164+ 'hidesysops', 'hidesysops', $this->opts->getValue( 'hidesysops' ) ) . '<br />';
 165+
 166+ $out .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n";# Submit button and form bottom
 167+ $out .= Xml::closeElement( 'fieldset' );
 168+ $out .= Xml::closeElement( 'form' );
 169+
 170+ return $out;
173171 }
174172 }
175173
@@ -204,7 +202,7 @@
205203 # getBody() first to check, if empty
206204 $usersbody = $up->getBody();
207205
208 - $out->addHTML( $up->buildHTMLForm() );
 206+ $out->addHTML( $up->getPageHeader() );
209207 if ( $usersbody ) {
210208 $out->addHTML(
211209 $up->getNavigationBar() .
Index: trunk/phase3/includes/specials/SpecialNewimages.php
@@ -30,15 +30,16 @@
3131 $this->setHeaders();
3232 $this->outputHeader();
3333
34 - $out = $this->getOutput();
3534 $pager = new NewFilesPager( $this->getContext(), $par );
3635
3736 if ( !$this->including() ) {
38 - $out->addHTML( $pager->buildHTMLForm() );
 37+ $form = $pager->getForm();
 38+ $form->prepareForm();
 39+ $form->displayForm( '' );
3940 }
40 - $out->addHTML( $pager->getBody() );
 41+ $this->getOutput()->addHTML( $pager->getBody() );
4142 if ( !$this->including() ) {
42 - $out->addHTML( $pager->getNavigationBar() );
 43+ $this->getOutput()->addHTML( $pager->getNavigationBar() );
4344 }
4445 }
4546 }
@@ -124,7 +125,7 @@
125126 );
126127 }
127128
128 - protected function getHTMLFormFields() {
 129+ function getForm() {
129130 global $wgMiserMode;
130131
131132 $fields = array(
@@ -137,21 +138,30 @@
138139 'type' => 'check',
139140 'label' => wfMessage( 'showhidebots', wfMsg( 'show' ) ),
140141 'name' => 'showbots',
 142+ # 'default' => $this->getRequest()->getBool( 'showbots', 0 ),
141143 ),
 144+ 'limit' => array(
 145+ 'type' => 'hidden',
 146+ 'default' => $this->getRequest()->getText( 'limit' ),
 147+ 'name' => 'limit',
 148+ ),
 149+ 'offset' => array(
 150+ 'type' => 'hidden',
 151+ 'default' => $this->getRequest()->getText( 'offset' ),
 152+ 'name' => 'offset',
 153+ ),
142154 );
143155
144156 if( $wgMiserMode ){
145157 unset( $fields['like'] );
146158 }
147159
148 - return $fields;
149 - }
 160+ $form = new HTMLForm( $fields, $this->getContext() );
 161+ $form->setTitle( $this->getTitle() );
 162+ $form->setSubmitText( wfMsg( 'ilsubmit' ) );
 163+ $form->setMethod( 'get' );
 164+ $form->setWrapperLegend( wfMsg( 'newimages-legend' ) );
150165
151 - protected function getHTMLFormLegend() {
152 - return 'newimages-legend';
 166+ return $form;
153167 }
154 -
155 - protected function getHTMLFormSubmit() {
156 - return 'ilsubmit';
157 - }
158168 }
Index: trunk/phase3/includes/Pager.php
@@ -100,13 +100,6 @@
101101 protected $mLastShown, $mFirstShown, $mPastTheEndIndex, $mDefaultQuery, $mNavigationBar;
102102
103103 /**
104 - * HTMLForm object
105 - *
106 - * @var HTMLForm
107 - */
108 - protected $mHTMLForm;
109 -
110 - /**
111104 * Result object for the query. Warning: seek before use.
112105 *
113106 * @var ResultWrapper
@@ -567,46 +560,6 @@
568561 }
569562
570563 /**
571 - * Assembles an HTMLForm for the Pager and returns the HTML
572 - *
573 - * @return string
574 - */
575 - public function buildHTMLForm() {
576 - if ( $this->getHTMLFormFields() === null ) {
577 - throw new MWException( __METHOD__ . " was called without any form fields being defined" );
578 - }
579 -
580 - $this->mHTMLForm = new HTMLForm( $this->getHTMLFormFields(), $this->getContext() );
581 - $this->mHTMLForm->setMethod( 'get' );
582 - $this->mHTMLForm->setWrapperLegendMsg( $this->getHTMLFormLegend() );
583 - $this->mHTMLForm->setSubmitTextMsg( $this->getHTMLFormSubmit() );
584 - $this->addHiddenFields();
585 - $this->modifyHTMLForm( $this->mHTMLForm );
586 - $this->mHTMLForm->prepareForm();
587 -
588 - return $this->mHTMLForm->getHTML( '' );
589 - }
590 -
591 - /**
592 - * Adds hidden elements to forms for things that are in the query string.
593 - * This is so that parameters like offset stick through form submissions
594 - */
595 - protected function addHiddenFields() {
596 - $query = $this->getRequest()->getQueryValues();
597 - $fieldsBlacklist = array( 'title' );
598 - $fields = $this->mHTMLForm->getFlatFields();
599 - foreach ( $fields as $name => $field ) {
600 - $fieldsBlacklist[] = $field->getName();
601 - }
602 - foreach ( $query as $name => $value ) {
603 - if ( in_array( $name, $fieldsBlacklist ) ) {
604 - continue;
605 - }
606 - $this->mHTMLForm->addHiddenField( $name, $value );
607 - }
608 - }
609 -
610 - /**
611564 * Abstract formatting function. This should return an HTML string
612565 * representing the result row $row. Rows will be concatenated and
613566 * returned by getBody()
@@ -682,43 +635,6 @@
683636 * @return Boolean
684637 */
685638 protected function getDefaultDirections() { return false; }
686 -
687 - /**
688 - * Returns an array for HTMLForm fields for the pager
689 - *
690 - * Only used if the pager makes use of HTMLForms
691 - *
692 - * @return array|null
693 - */
694 - protected function getHTMLFormFields() { return null; }
695 -
696 - /**
697 - * Message name for the fieldset legend text
698 - *
699 - * Only used if the pager makes use of HTMLForms
700 - *
701 - * @return string
702 - */
703 - protected function getHTMLFormLegend() { return ''; }
704 -
705 - /**
706 - * Message name for the submit button text
707 - *
708 - * Only used if the pager makes use of HTMLForms
709 - *
710 - * @return string
711 - */
712 - protected function getHTMLFormSubmit() { return ''; }
713 -
714 - /**
715 - * If the pager needs to do any modifications to the Form, override this
716 - * function.
717 - *
718 - * Only used if the pager makes use of HTMLForms
719 - *
720 - * @param HTMLForm $form
721 - */
722 - protected function modifyHTMLForm( HTMLForm $form ) {}
723639 }
724640
725641
@@ -1156,27 +1072,6 @@
11571073 }
11581074
11591075 /**
1160 - * Returns an HTMLFormField definition for the "Items per page:" dropdown
1161 - *
1162 - * @return array
1163 - */
1164 - protected function getHTMLFormLimitSelect() {
1165 - $f = array(
1166 - 'class' => 'HTMLItemsPerPageField',
1167 - 'label-message' => 'table_pager_limit_label',
1168 - 'options' => array(),
1169 - 'default' => $this->mDefaultLimit,
1170 - 'name' => 'limit',
1171 - );
1172 -
1173 - foreach( $this->mLimitsShown as $limit ) {
1174 - $f['options'][$this->getLanguage()->formatNum( $limit )] = $limit;
1175 - }
1176 -
1177 - return $f;
1178 - }
1179 -
1180 - /**
11811076 * Get <input type="hidden"> elements for use in a method="get" form.
11821077 * Resubmits all defined elements of the query string, except for a
11831078 * blacklist, passed in the $blacklist parameter.
@@ -1263,30 +1158,3 @@
12641159 */
12651160 abstract function getFieldNames();
12661161 }
1267 -
1268 -/**
1269 - * Items per page dropdown for HTMLForm
1270 - */
1271 -class HTMLItemsPerPageField extends HTMLSelectField {
1272 - /**
1273 - * Basically don't do any validation. If it's a number that's fine. Also,
1274 - * add it to the list if it's not there already
1275 - *
1276 - * @param $value
1277 - * @param $alldata
1278 - * @return bool
1279 - */
1280 - function validate( $value, $alldata ) {
1281 - if ( $value == '' ) {
1282 - return true;
1283 - }
1284 -
1285 - if ( !in_array( $value, $this->mParams['options'] ) ) {
1286 - $this->mParams['options'][ $this->mParent->getLanguage()->formatNum( $value ) ] = intval($value);
1287 - asort( $this->mParams['options'] );
1288 - }
1289 -
1290 - return true;
1291 - }
1292 -
1293 -}
\ No newline at end of file

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r104353This is the rework I was talking about in r104318 for 1.19. Instead of having...johnduhart18:23, 27 November 2011
r104354Followup r104353, fixing a regression in the BlockListjohnduhart18:28, 27 November 2011
r104356Followup r104353, updating Special:NewFilesjohnduhart19:03, 27 November 2011
r104358Followup r104353, updating Special:Categoriesjohnduhart19:17, 27 November 2011
r104383Followup r104353, updating Special:ProtectedTitles...johnduhart00:31, 28 November 2011

Status & tagging log