r40770 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r40769‎ | r40770 | r40771 >
Date:05:33, 13 September 2008
Author:mrzman
Status:old
Tags:
Comment:
(bug 12650) Make it possible to enter separate expiry times for each restriction type.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/Article.php (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/LogPage.php (modified) (history)
  • /trunk/phase3/includes/ProtectionForm.php (modified) (history)
  • /trunk/phase3/includes/Title.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialMovepage.php (modified) (history)
  • /trunk/phase3/languages/messages/MessagesEn.php (modified) (history)
  • /trunk/phase3/skins/common/protect.js (modified) (history)

Diff [purge]

Index: trunk/phase3/skins/common/protect.js
@@ -101,6 +101,40 @@
102102 }
103103
104104 /**
 105+ * When protection levels are locked together, update the
 106+ * expiries when one changes
 107+ *
 108+ * @param Element source expiry input that changed
 109+ */
 110+
 111+function protectExpiryUpdate(source) {
 112+ if( !protectUnchained() ) {
 113+ var expiry = source.value;
 114+ expiryForInputs(function(set) {
 115+ set.value = expiry;
 116+ });
 117+ }
 118+}
 119+
 120+/**
 121+ * When protection levels are locked together, update the
 122+ * expiry lists when one changes and clear the custom inputs
 123+ *
 124+ * @param Element source expiry selector that changed
 125+ */
 126+function protectExpiryListUpdate(source) {
 127+ if( !protectUnchained() ) {
 128+ var expiry = source.value;
 129+ expiryListForInputs(function(set) {
 130+ set.value = expiry;
 131+ });
 132+ expiryForInputs(function(set) {
 133+ set.value = '';
 134+ });
 135+ }
 136+}
 137+
 138+/**
105139 * Update chain status and enable/disable various bits of the UI
106140 * when the user changes the "unlock move permissions" checkbox
107141 */
@@ -200,8 +234,65 @@
201235 }
202236
203237 /**
204 - * Enable/disable protection selectors
 238+ * Apply a callback to each expiry input
205239 *
 240+ * @param callable func Callback function
 241+ */
 242+function expiryForInputs(func) {
 243+ var inputs = expiryInputs();
 244+ for (var i = 0; i < inputs.length; i++) {
 245+ func(inputs[i]);
 246+ }
 247+}
 248+
 249+/**
 250+ * Get a list of all expiry inputs on the page
 251+ *
 252+ * @return Array
 253+ */
 254+function expiryInputs() {
 255+ var all = document.getElementsByTagName("input");
 256+ var ours = new Array();
 257+ for (var i = 0; i < all.length; i++) {
 258+ var set = all[i];
 259+ if (set.name.match(/^mwProtect-expiry-/)) {
 260+ ours[ours.length] = set;
 261+ }
 262+ }
 263+ return ours;
 264+}
 265+
 266+/**
 267+ * Apply a callback to each expiry selector list
 268+ * @param callable func Callback function
 269+ */
 270+function expiryListForInputs(func) {
 271+ var inputs = expiryListInputs();
 272+ for (var i = 0; i < inputs.length; i++) {
 273+ func(inputs[i]);
 274+ }
 275+}
 276+
 277+/**
 278+ * Get a list of all expiry selector lists on the page
 279+ *
 280+ * @return Array
 281+ */
 282+function expiryListInputs() {
 283+ var all = document.getElementsByTagName("select");
 284+ var ours = new Array();
 285+ for (var i = 0; i < all.length; i++) {
 286+ var set = all[i];
 287+ if (set.id.match(/^mwProtectExpiryList-/)) {
 288+ ours[ours.length] = set;
 289+ }
 290+ }
 291+ return ours;
 292+}
 293+
 294+/**
 295+ * Enable/disable protection selectors and expiry inputs
 296+ *
206297 * @param boolean val Enable?
207298 */
208299 function protectEnable(val) {
@@ -215,4 +306,22 @@
216307 set.style.visible = val ? "visible" : "hidden";
217308 }
218309 });
 310+ first = true;
 311+ expiryForInputs(function(set) {
 312+ if (first) {
 313+ first = false;
 314+ } else {
 315+ set.disabled = !val;
 316+ set.style.visible = val ? "visible" : "hidden";
 317+ }
 318+ });
 319+ first = true;
 320+ expiryListForInputs(function(set) {
 321+ if (first) {
 322+ first = false;
 323+ } else {
 324+ set.disabled = !val;
 325+ set.style.visible = val ? "visible" : "hidden";
 326+ }
 327+ });
219328 }
Index: trunk/phase3/includes/ProtectionForm.php
@@ -25,8 +25,10 @@
2626 class ProtectionForm {
2727 var $mRestrictions = array();
2828 var $mReason = '';
 29+ var $mReasonList = '';
2930 var $mCascade = false;
30 - var $mExpiry = null;
 31+ var $mExpiry =array();
 32+ var $mExpiryList = array();
3133 var $mPermErrors = array();
3234 var $mApplicableTypes = array();
3335
@@ -44,18 +46,17 @@
4547 // Fixme: this form currently requires individual selections,
4648 // but the db allows multiples separated by commas.
4749 $this->mRestrictions[$action] = implode( '', $this->mTitle->getRestrictions( $action ) );
 50+
 51+ if ( $this->mTitle->mRestrictionsExpiry[$action] == 'infinity' ) {
 52+ $this->mExpiry[$action] = 'infinite';
 53+ } else if ( strlen($this->mTitle->mRestrictionsExpiry[$action]) == 0 ) {
 54+ $this->mExpiry[$action] = '';
 55+ } else {
 56+ // FIXME: this format is not user friendly
 57+ $this->mExpiry[$action] = wfTimestamp( TS_ISO_8601, $this->mTitle->mRestrictionsExpiry[$action] );
 58+ }
4859 }
49 -
5060 $this->mCascade = $this->mTitle->areRestrictionsCascading();
51 -
52 - if ( $this->mTitle->mRestrictionsExpiry == 'infinity' ) {
53 - $this->mExpiry = 'infinite';
54 - } else if ( strlen($this->mTitle->mRestrictionsExpiry) == 0 ) {
55 - $this->mExpiry = '';
56 - } else {
57 - // FIXME: this format is not user friendly
58 - $this->mExpiry = wfTimestamp( TS_ISO_8601, $this->mTitle->mRestrictionsExpiry );
59 - }
6061 }
6162
6263 // The form will be available in read-only to show levels.
@@ -67,14 +68,15 @@
6869 $this->mReason = $wgRequest->getText( 'mwProtect-reason' );
6970 $this->mReasonList = $wgRequest->getText( 'wpProtectReasonList' );
7071 $this->mCascade = $wgRequest->getBool( 'mwProtect-cascade', $this->mCascade );
71 - // Let dropdown have 'infinite' for unprotected pages
72 - if( !($expiry = $wgRequest->getText( 'mwProtect-expiry' )) && $this->mExpiry != 'infinite' ) {
73 - $expiry = $this->mExpiry;
74 - }
75 - $this->mExpiry = $expiry;
76 - $this->mExpiryList = $wgRequest->getText( 'wpProtectExpiryList', $this->mExpiry ? '' : 'infinite' );
77 -
 72+
7873 foreach( $this->mApplicableTypes as $action ) {
 74+ // Let dropdown have 'infinite' for unprotected pages
 75+ if( !($expiry[$action] = $wgRequest->getText( "mwProtect-expiry-$action" )) && $this->mExpiry[$action] != 'infinite' ) {
 76+ $expiry[$action] = $this->mExpiry[$action];
 77+ }
 78+ $this->mExpiry[$action] = $expiry[$action];
 79+ $this->mExpiryList[$action] = $wgRequest->getText( "wpProtectExpiryList-$action", $this->mExpiry[$action] ? '' : 'infinite' );
 80+
7981 $val = $wgRequest->getVal( "mwProtect-level-$action" );
8082 if( isset( $val ) && in_array( $val, $wgRestrictionLevels ) ) {
8183 // Prevent users from setting levels that they cannot later unset
@@ -175,32 +177,35 @@
176178 } elseif ( $reasonstr == 'other' ) {
177179 $reasonstr = $this->mReason;
178180 }
179 - # Custom expiry takes precedence
180 - if ( strlen( $this->mExpiry ) == 0 ) {
181 - $this->mExpiry = strlen($this->mExpiryList) ? $this->mExpiryList : 'infinite';
182 - }
183 -
184 - if ( $this->mExpiry == 'infinite' || $this->mExpiry == 'indefinite' ) {
185 - $expiry = Block::infinity();
186 - } else {
187 - # Convert GNU-style date, on error returns -1 for PHP <5.1 and false for PHP >=5.1
188 - $expiry = strtotime( $this->mExpiry );
189 -
190 - if ( $expiry < 0 || $expiry === false ) {
191 - $this->show( wfMsg( 'protect_expiry_invalid' ) );
192 - return false;
 181+ $expiry = array();
 182+ foreach( $this->mApplicableTypes as $action ) {
 183+ # Custom expiry takes precedence
 184+ if ( strlen( $wgRequest->getText( "mwProtect-expiry-$action" ) ) == 0 ) {
 185+ $this->mExpiry[$action] = strlen($wgRequest->getText( "wpProtectExpiryList-$action")) ? $wgRequest->getText( "wpProtectExpiryList-$action") : 'infinite';
 186+ } else {
 187+ $this->mExpiry[$action] = $wgRequest->getText( "mwProtect-expiry-$action" );
193188 }
 189+ if ( $this->mExpiry[$action] == 'infinite' || $this->mExpiry[$action] == 'indefinite' ) {
 190+ $expiry[$action] = Block::infinity();
 191+ } else {
 192+ # Convert GNU-style date, on error returns -1 for PHP <5.1 and false for PHP >=5.1
 193+ $expiry[$action] = strtotime( $this->mExpiry[$action] );
194194
195 - // Fixme: non-qualified absolute times are not in users specified timezone
196 - // and there isn't notice about it in the ui
197 - $expiry = wfTimestamp( TS_MW, $expiry );
 195+ if ( $expiry[$action] < 0 || $expiry[$action] === false ) {
 196+ $this->show( wfMsg( 'protect_expiry_invalid' ) );
 197+ return false;
 198+ }
198199
199 - if ( $expiry < wfTimestampNow() ) {
200 - $this->show( wfMsg( 'protect_expiry_old' ) );
201 - return false;
 200+ // Fixme: non-qualified absolute times are not in users specified timezone
 201+ // and there isn't notice about it in the ui
 202+ $expiry[$action] = wfTimestamp( TS_MW, $expiry[$action] );
 203+
 204+ if ( $expiry[$action] < wfTimestampNow() ) {
 205+ $this->show( wfMsg( 'protect_expiry_old' ) );
 206+ return false;
 207+ }
202208 }
203209 }
204 -
205210 # They shouldn't be able to do this anyway, but just to make sure, ensure that cascading restrictions aren't being applied
206211 # to a semi-protected page.
207212 global $wgGroupPermissions;
@@ -214,7 +219,7 @@
215220 if ($this->mTitle->exists()) {
216221 $ok = $this->mArticle->updateRestrictions( $this->mRestrictions, $reasonstr, $this->mCascade, $expiry );
217222 } else {
218 - $ok = $this->mTitle->updateTitleProtection( $this->mRestrictions['create'], $reasonstr, $expiry );
 223+ $ok = $this->mTitle->updateTitleProtection( $this->mRestrictions['create'], $reasonstr, $expiry['create'] );
219224 }
220225
221226 if( !$ok ) {
@@ -238,8 +243,6 @@
239244 function buildForm() {
240245 global $wgUser;
241246
242 - $mProtectexpiry = Xml::label( wfMsg( 'protectexpiry' ), 'mwProtectExpiryList' );
243 - $mProtectother = Xml::label( wfMsg( 'protect-othertime' ), 'expires' );
244247 $mProtectreasonother = Xml::label( wfMsg( 'protectcomment' ), 'wpProtectReasonList' );
245248 $mProtectreason = Xml::label( wfMsg( 'protect-otherreason' ), 'mwProtect-reason' );
246249
@@ -257,10 +260,9 @@
258261 $out .= Xml::openElement( 'fieldset' ) .
259262 Xml::element( 'legend', null, wfMsg( 'protect-legend' ) ) .
260263 Xml::openElement( 'table', array( 'id' => 'mwProtectSet' ) ) .
261 - Xml::openElement( 'tbody' ) .
262 - "<tr>\n";
 264+ Xml::openElement( 'tbody' );
263265
264 - foreach( $this->mRestrictions as $action => $required ) {
 266+ foreach( $this->mRestrictions as $action => $selected ) {
265267 /* Not all languages have V_x <-> N_x relation */
266268 $msg = wfMsg( 'restriction-' . $action );
267269 if( wfEmptyMsg( 'restriction-' . $action, $msg ) ) {
@@ -269,32 +271,53 @@
270272 $label = Xml::element( 'label',
271273 array( 'for' => "mwProtect-level-$action" ),
272274 $msg );
273 - $out .= "<th>$label</th>";
274 - }
275 - $out .= "</tr>
276 - <tr>\n";
277 - foreach( $this->mRestrictions as $action => $selected ) {
278 - $out .= "<td>" .
279 - $this->buildSelector( $action, $selected ) .
280 - "</td>";
281 - }
282 - $out .= "</tr>\n";
283 -
284 - $scExpiryOptions = wfMsgForContent( 'ipboptions' ); // FIXME: use its own message
 275+ $out .= "<tr><th>$label</th></tr>";
 276+ $out .= "<tr><td>" .
 277+ $this->buildSelector( $action, $selected ) .
 278+ "</td></tr>";
 279+ $scExpiryOptions = wfMsgForContent( 'ipboptions' ); // FIXME: use its own message
285280
286 - $showProtectOptions = ($scExpiryOptions !== '-' && !$this->disabled);
287 - if( !$showProtectOptions )
288 - $mProtectother = $mProtectexpiry;
289 -
290 - $expiryFormOptions = Xml::option( wfMsg( 'protect-othertime-op' ), 'wpProtectExpiryList' );
291 - foreach( explode(',', $scExpiryOptions) as $option ) {
292 - if ( strpos($option, ":") === false ) $option = "$option:$option";
293 - list($show, $value) = explode(":", $option);
294 - $show = htmlspecialchars($show);
295 - $value = htmlspecialchars($value);
296 - $expiryFormOptions .= Xml::option( $show, $value, $this->mExpiryList === $value ? true : false ) . "\n";
 281+ $showProtectOptions = ($scExpiryOptions !== '-' && !$this->disabled);
 282+
 283+ $mProtectexpiry = Xml::label( wfMsg( 'protectexpiry' ), "mwProtectExpiryList-$action" );
 284+ $mProtectother = Xml::label( wfMsg( 'protect-othertime' ), "mwProtect-$action-expires" );
 285+ $expiryFormOptions = Xml::option( wfMsg( 'protect-othertime-op' ), "wpProtectExpiryList-$action" );
 286+ foreach( explode(',', $scExpiryOptions) as $option ) {
 287+ if ( strpos($option, ":") === false ) $option = "$option:$option";
 288+ list($show, $value) = explode(":", $option);
 289+ $show = htmlspecialchars($show);
 290+ $value = htmlspecialchars($value);
 291+ $expiryFormOptions .= Xml::option( $show, $value, $this->mExpiryList[$action] === $value ? true : false ) . "\n";
 292+ }
 293+ # Add expiry dropdown
 294+ if( $showProtectOptions && !$this->disabled ) {
 295+ $out .= "
 296+ <tr>
 297+ <td class='mw-label'>
 298+ {$mProtectexpiry}
 299+ </td>
 300+ <td class='mw-input'>" .
 301+ Xml::tags( 'select',
 302+ array(
 303+ 'id' => "mwProtectExpiryList-$action",
 304+ 'name' => "wpProtectExpiryList-$action",
 305+ 'onchange' => "protectExpiryListUpdate(this)",
 306+ 'tabindex' => '2' ) + $this->disabledAttrib,
 307+ $expiryFormOptions ) .
 308+ "</td>
 309+ </tr>";
 310+ }
 311+ # Add custom expiry field
 312+ $attribs = array( 'id' => "mwProtect-$action-expires", 'onkeyup' => 'protectExpiryUpdate(this)' ) + $this->disabledAttrib;
 313+ $out .= "<tr>
 314+ <td class='mw-label'>" .
 315+ $mProtectother .
 316+ '</td>
 317+ <td class="mw-input">' .
 318+ Xml::input( "mwProtect-expiry-$action", 60, $this->mExpiry[$action], $attribs ) .
 319+ '</td>
 320+ </tr>';
297321 }
298 -
299322 $reasonDropDown = Xml::listDropDown( 'wpProtectReasonList',
300323 wfMsgForContent( 'protect-dropdown' ),
301324 wfMsgForContent( 'protect-otherreason-op' ), '', 'mwProtect-reason', 4 );
@@ -314,34 +337,6 @@
315338 "</td>
316339 </tr>\n";
317340 }
318 - # Add expiry dropdown
319 - if( $showProtectOptions && !$this->disabled ) {
320 - $out .= "
321 - <tr>
322 - <td class='mw-label'>
323 - {$mProtectexpiry}
324 - </td>
325 - <td class='mw-input'>" .
326 - Xml::tags( 'select',
327 - array(
328 - 'id' => 'mwProtectExpiryList',
329 - 'name' => 'wpProtectExpiryList',
330 - 'onchange' => "document.getElementById('expires').value='';",
331 - 'tabindex' => '2' ) + $this->disabledAttrib,
332 - $expiryFormOptions ) .
333 - "</td>
334 - </tr>";
335 - }
336 - # Add custom expiry field
337 - $attribs = array( 'id' => 'expires' ) + $this->disabledAttrib;
338 - $out .= "<tr>
339 - <td class='mw-label'>" .
340 - $mProtectother .
341 - '</td>
342 - <td class="mw-input">' .
343 - Xml::input( 'mwProtect-expiry', 60, $this->mExpiry, $attribs ) .
344 - '</td>
345 - </tr>';
346341 # Add manual and custom reason field/selects
347342 if( !$this->disabled ) {
348343 $out .= "
Index: trunk/phase3/includes/Article.php
@@ -1798,7 +1798,7 @@
17991799 * @param string $reason
18001800 * @return bool true on success
18011801 */
1802 - function updateRestrictions( $limit = array(), $reason = '', $cascade = 0, $expiry = null ) {
 1802+ function updateRestrictions( $limit = array(), $reason = '', $cascade = 0, $expiry = array() ) {
18031803 global $wgUser, $wgRestrictionTypes, $wgContLang;
18041804
18051805 $id = $this->mTitle->getArticleID();
@@ -1816,15 +1816,17 @@
18171817 # FIXME: Same limitations as described in ProtectionForm.php (line 37);
18181818 # we expect a single selection, but the schema allows otherwise.
18191819 $current = array();
1820 - foreach( $wgRestrictionTypes as $action )
 1820+ $updated = Article::flattenRestrictions( $limit );
 1821+ $changed = false;
 1822+ foreach( $wgRestrictionTypes as $action ) {
18211823 $current[$action] = implode( '', $this->mTitle->getRestrictions( $action ) );
 1824+ $changed = ($changed || ($this->mTitle->mRestrictionsExpiry[$action] != $expiry[$action]) );
 1825+ }
18221826
18231827 $current = Article::flattenRestrictions( $current );
1824 - $updated = Article::flattenRestrictions( $limit );
18251828
1826 - $changed = ( $current != $updated );
 1829+ $changed = ($changed || ( $current != $updated ) );
18271830 $changed = $changed || ($updated && $this->mTitle->areRestrictionsCascading() != $cascade);
1828 - $changed = $changed || ($updated && $this->mTitle->mRestrictionsExpiry != $expiry);
18291831 $protect = ( $updated != '' );
18301832
18311833 # If nothing's changed, do nothing
@@ -1832,14 +1834,6 @@
18331835 if( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser, $limit, $reason ) ) ) {
18341836
18351837 $dbw = wfGetDB( DB_MASTER );
1836 -
1837 - $encodedExpiry = Block::encodeExpiry($expiry, $dbw );
1838 -
1839 - $expiry_description = '';
1840 - if( $encodedExpiry != 'infinity' ) {
1841 - $expiry_description = ' (' . wfMsgForContent( 'protect-expiring',
1842 - $wgContLang->timeanddate( $expiry, false, false ) ).')';
1843 - }
18441838
18451839 # Prepare a null revision to be added to the history
18461840 $modified = $current != '' && $protect;
@@ -1859,7 +1853,6 @@
18601854 break;
18611855 }
18621856 }
1863 -
18641857 $cascade_description = '';
18651858 if( $cascade ) {
18661859 $cascade_description = ' ['.wfMsgForContent('protect-summary-cascade').']';
@@ -1869,10 +1862,23 @@
18701863 $comment .= ": $reason";
18711864
18721865 $editComment = $comment;
1873 - if( $protect )
1874 - $editComment .= " [$updated]";
1875 - if( $expiry_description && $protect )
1876 - $editComment .= "$expiry_description";
 1866+ $encodedExpiry = array();
 1867+ $protect_description = '';
 1868+ foreach( $limit as $action => $restrictions ) {
 1869+ $encodedExpiry[$action] = Block::encodeExpiry($expiry[$action], $dbw );
 1870+ if ($restrictions != '') {
 1871+ $protect_description .= "[$action=$restrictions] (";
 1872+ if( $encodedExpiry[$action] != 'infinity' ) {
 1873+ $protect_description .= wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry[$action], false, false ) );
 1874+ } else {
 1875+ $protect_description .= wfMsgForContent( 'protect-expiry-indefinite' );
 1876+ }
 1877+ $protect_description .= ') ';
 1878+ }
 1879+ }
 1880+
 1881+ if( $protect_description && $protect )
 1882+ $editComment .= "($protect_description)";
18771883 if( $cascade )
18781884 $editComment .= "$cascade_description";
18791885 # Update restrictions table
@@ -1880,8 +1886,8 @@
18811887 if ($restrictions != '' ) {
18821888 $dbw->replace( 'page_restrictions', array(array('pr_page', 'pr_type')),
18831889 array( 'pr_page' => $id, 'pr_type' => $action
1884 - , 'pr_level' => $restrictions, 'pr_cascade' => $cascade ? 1 : 0
1885 - , 'pr_expiry' => $encodedExpiry ), __METHOD__ );
 1890+ , 'pr_level' => $restrictions, 'pr_cascade' => $cascade && $action == 'edit' ? 1 : 0
 1891+ , 'pr_expiry' => $encodedExpiry[$action] ), __METHOD__ );
18861892 } else {
18871893 $dbw->delete( 'page_restrictions', array( 'pr_page' => $id,
18881894 'pr_type' => $action ), __METHOD__ );
@@ -1910,7 +1916,7 @@
19111917 # Update the protection log
19121918 $log = new LogPage( 'protect' );
19131919 if( $protect ) {
1914 - $params = array($updated,$encodedExpiry,$cascade ? 'cascade' : '');
 1920+ $params = array($protect_description,$cascade ? 'cascade' : '');
19151921 $log->addEntry( $modified ? 'modify' : 'protect', $this->mTitle, trim( $reason), $params );
19161922 } else {
19171923 $log->addEntry( 'unprotect', $this->mTitle, $reason );
Index: trunk/phase3/includes/Title.php
@@ -56,7 +56,7 @@
5757 var $mRestrictions = array(); ///< Array of groups allowed to edit this article
5858 var $mOldRestrictions = false;
5959 var $mCascadeRestriction; ///< Cascade restrictions on this page to included templates and images?
60 - var $mRestrictionsExpiry; ///< When do the restrictions on this page expire?
 60+ var $mRestrictionsExpiry = array(); ///< When do the restrictions on this page expire?
6161 var $mHasCascadingRestrictions; ///< Are cascading restrictions in effect on this page?
6262 var $mCascadeSources; ///< Where are the cascading restrictions coming from on this page?
6363 var $mRestrictionsLoaded = false; ///< Boolean for initialisation on demand
@@ -1368,7 +1368,7 @@
13691369 global $wgUser,$wgContLang;
13701370
13711371 if ($create_perm == implode(',',$this->getRestrictions('create'))
1372 - && $expiry == $this->mRestrictionsExpiry) {
 1372+ && $expiry == $this->mRestrictionsExpiry['create']) {
13731373 // No change
13741374 return true;
13751375 }
@@ -1383,7 +1383,10 @@
13841384 if ( $encodedExpiry != 'infinity' ) {
13851385 $expiry_description = ' (' . wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry ) ).')';
13861386 }
1387 -
 1387+ else {
 1388+ $expiry_description .= ' (' . wfMsgForContent( 'protect-expiry-indefinite' ).')';
 1389+ }
 1390+
13881391 # Update protection table
13891392 if ($create_perm != '' ) {
13901393 $dbw->replace( 'protected_titles', array(array('pt_namespace', 'pt_title')),
@@ -1740,7 +1743,6 @@
17411744 } else {
17421745 $this->mHasCascadingRestrictions = $sources;
17431746 }
1744 -
17451747 return array( $sources, $pagerestrictions );
17461748 }
17471749
@@ -1762,10 +1764,10 @@
17631765
17641766 foreach( $wgRestrictionTypes as $type ){
17651767 $this->mRestrictions[$type] = array();
 1768+ $this->mRestrictionsExpiry[$type] = Block::decodeExpiry('');
17661769 }
17671770
17681771 $this->mCascadeRestriction = false;
1769 - $this->mRestrictionsExpiry = Block::decodeExpiry('');
17701772
17711773 # Backwards-compatibility: also load the restrictions from the page record (old format).
17721774
@@ -1809,7 +1811,7 @@
18101812
18111813 // Only apply the restrictions if they haven't expired!
18121814 if ( !$expiry || $expiry > $now ) {
1813 - $this->mRestrictionsExpiry = $expiry;
 1815+ $this->mRestrictionsExpiry[$row->pr_type] = $expiry;
18141816 $this->mRestrictions[$row->pr_type] = explode( ',', trim( $row->pr_level ) );
18151817
18161818 $this->mCascadeRestriction |= $row->pr_cascade;
@@ -1850,13 +1852,13 @@
18511853
18521854 if (!$expiry || $expiry > $now) {
18531855 // Apply the restrictions
1854 - $this->mRestrictionsExpiry = $expiry;
 1856+ $this->mRestrictionsExpiry['create'] = $expiry;
18551857 $this->mRestrictions['create'] = explode(',', trim($pt_create_perm) );
18561858 } else { // Get rid of the old restrictions
18571859 Title::purgeExpiredRestrictions();
18581860 }
18591861 } else {
1860 - $this->mRestrictionsExpiry = Block::decodeExpiry('');
 1862+ $this->mRestrictionsExpiry['create'] = Block::decodeExpiry('');
18611863 }
18621864 $this->mRestrictionsLoaded = true;
18631865 }
Index: trunk/phase3/includes/DefaultSettings.php
@@ -1383,7 +1383,7 @@
13841384 * to ensure that client-side caches don't keep obsolete copies of global
13851385 * styles.
13861386 */
1387 -$wgStyleVersion = '176';
 1387+$wgStyleVersion = '177';
13881388
13891389
13901390 # Server-side caching:
Index: trunk/phase3/includes/specials/SpecialMovepage.php
@@ -292,6 +292,10 @@
293293
294294 $error = $ot->moveTo( $nt, true, $this->reason );
295295 if ( $error !== true ) {
 296+ if (isset($error[0][0]) && $error[0][0] = 'cascadeprotected') {
 297+ $wgOut->showPermissionsErrorPage($error, 'move');
 298+ return;
 299+ }
296300 # FIXME: showForm() should handle multiple errors
297301 call_user_func_array(array($this, 'showForm'), $error[0]);
298302 return;
Index: trunk/phase3/includes/LogPage.php
@@ -203,13 +203,9 @@
204204 }
205205 $params[2] = isset( $params[2] ) ?
206206 self::formatBlockFlags( $params[2], is_null( $skin ) ) : '';
207 - } else if ( $type == 'protect' && count($params) == 4 ) {
208 - $details .= " [{$params[1]}]"; // the restrictions
209 - if( $params[2] != 'infinity' ) {
210 - $details .= ' (' . wfMsgForContent( 'protect-expiring',
211 - $wgContLang->timeanddate( $params[2], false, false ) ).')';
212 - }
213 - if( $params[3] ) {
 207+ } else if ( $type == 'protect' && count($params) == 3 ) {
 208+ $details .= " {$params[1]}"; // restrictions and expiries
 209+ if( $params[2] ) {
214210 $details .= ' ['.wfMsg('protect-summary-cascade').']';
215211 }
216212 }
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -2315,6 +2315,7 @@
23162316 'protect-level-sysop' => 'Sysops only',
23172317 'protect-summary-cascade' => 'cascading',
23182318 'protect-expiring' => 'expires $1 (UTC)',
 2319+'protect-expiry-indefinite' => 'indefinite',
23192320 'protect-cascade' => 'Protect pages included in this page (cascading protection)',
23202321 'protect-cantedit' => 'You cannot change the protection levels of this page, because you do not have permission to edit it.',
23212322 'protect-othertime' => 'Other time:',
Index: trunk/phase3/RELEASE-NOTES
@@ -124,6 +124,8 @@
125125 * (bug 15551) Deletion log excerpt is now shown whenever a user vists a
126126 deleted page, even if they are unable to edit it.
127127 * Added Wantedfiles special pages, allowing users to find image links with no image.
 128+* (bug 12650) It is now possible to set different expiration times for different
 129+ restriction types on the protection form.
128130
129131 === Bug fixes in 1.14 ===
130132

Follow-up revisions

RevisionCommit summaryAuthorDate
r40779Cleanup after r40723, r40769, and r40770. C'mon guys. Messages need to be reg...siebrand08:32, 13 September 2008
r40780Cleanup for r40770:...aaron08:53, 13 September 2008

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r40601Pass in $latest value (for bug 12650)aaron23:31, 7 September 2008