r66549 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r66548‎ | r66549 | r66550 >
Date:20:55, 16 May 2010
Author:aaron
Status:deferred
Tags:
Comment:
* Refactorted stabilization code:
** Separate classes for special page and form logic
** Different subclasses used for protection and regular form case
** Moved more error handling/validation there
* Fixed silly API fatal
Modified paths:
  • /trunk/extensions/FlaggedRevs/FlaggedRevs.hooks.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/FlaggedRevs.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/api/ApiStabilize.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/forms (added) (history)
  • /trunk/extensions/FlaggedRevs/forms/FlaggedRevsConfigForm.php (added) (history)
  • /trunk/extensions/FlaggedRevs/language/Stabilization.i18n.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/specialpages/Stabilization_body.php (modified) (history)

Diff [purge]

Index: trunk/extensions/FlaggedRevs/FlaggedRevs.php
@@ -334,6 +334,10 @@
335335
336336 # Load review UI
337337 $wgAutoloadClasses['RevisionReview'] = $dir . 'specialpages/RevisionReview_body.php';
 338+# Load protection/stability UI
 339+$wgAutoloadClasses['FlaggedRevsConfigForm'] = $dir . 'forms/FlaggedRevsConfigForm.php';
 340+$wgAutoloadClasses['PageStabilityForm'] = $dir . 'forms/FlaggedRevsConfigForm.php';
 341+$wgAutoloadClasses['PageStabilityProtectForm'] = $dir . 'forms/FlaggedRevsConfigForm.php';
338342
339343 # Load reviewed versions UI
340344 $wgAutoloadClasses['ReviewedVersions'] = $dir . 'specialpages/ReviewedVersions_body.php';
Index: trunk/extensions/FlaggedRevs/language/Stabilization.i18n.php
@@ -42,10 +42,16 @@
4343 'stabilization-def-short' => 'Default',
4444 'stabilization-def-short-0' => 'Current',
4545 'stabilization-def-short-1' => 'Published',
46 - 'stabilize_expiry_invalid' => 'Invalid expiration date.',
47 - 'stabilize_expiry_old' => 'This expiration time has already passed.',
48 - 'stabilize-expiring' => 'expires $1 (UTC)',
49 - 'stabilization-review' => 'Mark the current revision checked',
 46+ 'stabilize_page_invalid' => 'The target page title is invalid.',
 47+ 'stabilize_page_notexists' => 'The target page does not exist.',
 48+ 'stabilize_page_unreviewable' => 'The target page is not in reviewable namespace.',
 49+ 'stabilize_invalid_precedence' => 'Invalid version precedence.',
 50+ 'stabilize_invalid_autoreview' => 'Invalid autoreview restriction',
 51+ 'stabilize_invalid_level' => 'Invalid protection level.',
 52+ 'stabilize_expiry_invalid' => 'Invalid expiration date.',
 53+ 'stabilize_expiry_old' => 'This expiration time has already passed.',
 54+ 'stabilize-expiring' => 'expires $1 (UTC)',
 55+ 'stabilization-review' => 'Mark the current revision checked',
5056 );
5157
5258 /** Message documentation (Message documentation)
Index: trunk/extensions/FlaggedRevs/forms/FlaggedRevsConfigForm.php
@@ -0,0 +1,610 @@
 2+<?php
 3+if ( !defined( 'MEDIAWIKI' ) ) {
 4+ echo "FlaggedRevs extension\n";
 5+ exit( 1 );
 6+}
 7+/**
 8+ * Class containing stability settings form business logic
 9+ *
 10+ * Note: handleParams() must be called after the user parameters are set
 11+ */
 12+abstract class FlaggedRevsConfigForm
 13+{
 14+ /* Form parameters which can be user given */
 15+ protected $target = null; # Target page text
 16+ protected $watchThis = null; # Watch checkbox
 17+ protected $reviewThis = null; # Auto-review option...
 18+ protected $reason = ''; # Custom/extra reason
 19+ protected $reasonSelection = ''; # Reason dropdown key
 20+ protected $expiry = ''; # Custom expiry
 21+ protected $expirySelection = ''; # Expiry dropdown key
 22+ protected $override = -1; # Default version
 23+ protected $autoreview = ''; # Autoreview restrictions...
 24+ protected $wasPosted = false; # POST request?
 25+
 26+ protected $page = false; # Target page obj (of $target)
 27+ protected $oldConfig = array(); # Old page config
 28+ protected $oldExpiry = ''; # Old page config expiry (GMT)
 29+ protected $isAllowed = null; # $wgUser can submit?
 30+
 31+ protected $submitLock = 1; # Disallow bad submissions
 32+
 33+ public function getTarget() {
 34+ return $this->target;
 35+ }
 36+
 37+ public function setTarget( $value ) {
 38+ $this->trySet( $this->target, $value );
 39+ }
 40+
 41+ public function getWatchThis() {
 42+ return $this->watchThis;
 43+ }
 44+
 45+ public function setWatchThis( $value ) {
 46+ $this->trySet( $this->watchThis, $value );
 47+ }
 48+
 49+ public function getReason() {
 50+ return $this->reason;
 51+ }
 52+
 53+ public function setReason( $value ) {
 54+ $this->trySet( $this->reason, $value );
 55+ }
 56+
 57+ public function getReasonSelection() {
 58+ return $this->reasonSelection;
 59+ }
 60+
 61+ public function setReasonSelection( $value ) {
 62+ $this->trySet( $this->reasonSelection, $value );
 63+ }
 64+
 65+ public function getExpiry() {
 66+ return $this->expiry;
 67+ }
 68+
 69+ public function setExpiry( $value ) {
 70+ $this->trySet( $this->expiry, $value );
 71+ }
 72+
 73+ public function getExpirySelection() {
 74+ return $this->expirySelection;
 75+ }
 76+
 77+ public function setExpirySelection( $value ) {
 78+ $this->trySet( $this->expirySelection, $value );
 79+ }
 80+
 81+ public function getAutoreview() {
 82+ return $this->autoreview;
 83+ }
 84+
 85+ public function setAutoreview( $value ) {
 86+ $this->trySet( $this->autoreview, $value );
 87+ }
 88+
 89+ public function setWasPosted( $value ) {
 90+ $this->trySet( $this->wasPosted, $value );
 91+ }
 92+
 93+ /**
 94+ * Set a member field to a value if the fields are unlocked
 95+ */
 96+ protected function trySet( &$field, $value ) {
 97+ if ( $this->submitLock ) {
 98+ $field = $value; // submission locked => still allowing input
 99+ } else {
 100+ throw new MWException( "FlaggedRevsConfigForm fields cannot be set after validation.\n");
 101+ }
 102+ }
 103+
 104+ /**
 105+ * Verify and clean up parameters and preload data from DB.
 106+ * Locks the member fields from being set.
 107+ *
 108+ * Note: some items may not all be set on failure.
 109+ * @return mixed (true on success, error string on failure)
 110+ */
 111+ public function handleParams() {
 112+ $this->page = Title::newFromURL( $this->target );
 113+ if ( is_null( $this->page ) ) {
 114+ return 'stabilize_page_invalid'; // page title is invalid
 115+ } elseif ( !$this->page->exists() ) {
 116+ return 'stabilize_page_notexists'; // page must exist
 117+ } elseif ( !FlaggedRevs::inReviewNamespace( $this->page ) ) {
 118+ return 'stabilize_page_unreviewable';
 119+ }
 120+ # Get the current page config and GMT expiry
 121+ $this->oldConfig = FlaggedRevs::getPageVisibilitySettings( $this->page, FR_MASTER );
 122+ $this->oldExpiry = $this->oldConfig['expiry'] === 'infinity'
 123+ ? 'infinite'
 124+ : wfTimestamp( TS_RFC2822, $this->oldConfig['expiry'] );
 125+ # Handle views (GET)
 126+ if ( !$this->wasPosted ) {
 127+ # Fill in existing settings
 128+ $ok = $this->preloadSettings();
 129+ # Handle submission data (POST)
 130+ } else {
 131+ $ok = $this->handlePostedParams();
 132+ }
 133+ if ( $ok === true && $this->wasPosted ) {
 134+ $this->submitLock = 0;
 135+ }
 136+ return $ok;
 137+ }
 138+
 139+ /*
 140+ * Preload existing page settings
 141+ * @return mixed (true on success, error string on failure)
 142+ */
 143+ protected function preloadSettings() {
 144+ return true;
 145+ }
 146+
 147+ /*
 148+ * Verify and clean up parameters from POST request.
 149+ * @return mixed (true on success, error string on failure)
 150+ */
 151+ protected function handlePostedParams() {
 152+ return true;
 153+ }
 154+
 155+ /*
 156+ * Gets the target page Obj
 157+ * @return mixed (Title or null)
 158+ */
 159+ public function getPage() {
 160+ if ( $this->page === false ) {
 161+ $this->handleParams(); // handleParams() not called first
 162+ }
 163+ return $this->page;
 164+ }
 165+
 166+ /*
 167+ * Gets the current config expiry in GTM (or 'infinite')
 168+ * @return string
 169+ */
 170+ public function getOldExpiryGMT() {
 171+ if ( $this->page === false ) {
 172+ $this->handleParams(); // handleParams() not called first
 173+ }
 174+ return $this->oldExpiry;
 175+ }
 176+
 177+ /*
 178+ * Can the user change the settings for this page?
 179+ * Note: if the current autoreview restriction is too high for this user
 180+ * then this will return false. Use for form selectors.
 181+ * @return bool
 182+ */
 183+ public function isAllowed() {
 184+ if ( $this->page === false ) {
 185+ $this->handleParams(); // handleParams() not called first
 186+ }
 187+ if ( $this->isAllowed === null ) {
 188+ # Users who cannot edit or review the page cannot set this
 189+ $this->isAllowed = ( $this->page
 190+ && $this->page->userCan( 'stablesettings' )
 191+ && $this->page->userCan( 'edit' )
 192+ && $this->page->userCan( 'review' )
 193+ );
 194+ }
 195+ return $this->isAllowed;
 196+ }
 197+
 198+ /**
 199+ * Verify and clean up parameters and preload data from DB.
 200+ * Note: some items may not all be set on failure.
 201+ * @return mixed (true on success, error string on failure)
 202+ */
 203+ public function submit() {
 204+ global $wgUser;
 205+ if ( $this->submitLock ) {
 206+ throw new MWException( "FlaggedRevsConfigForm::submit() called either " .
 207+ "without calling handleParams() or called in spite of its failure.\n" );
 208+ }
 209+ # Are we are going back to site defaults?
 210+ $reset = $this->newConfigIsReset();
 211+ # Parse and cleanup the expiry time given...
 212+ if ( $reset || $this->expiry == 'infinite' || $this->expiry == 'indefinite' ) {
 213+ $this->expiry = Block::infinity(); // normalize to 'infinity'
 214+ } else {
 215+ # Convert GNU-style date, on error returns -1 for PHP <5.1 and false for PHP >=5.1
 216+ $this->expiry = strtotime( $this->expiry );
 217+ if ( $this->expiry < 0 || $this->expiry === false ) {
 218+ return 'stabilize_expiry_invalid';
 219+ }
 220+ # Convert date to MW timestamp format
 221+ $this->expiry = wfTimestamp( TS_MW, $this->expiry );
 222+ if ( $this->expiry < wfTimestampNow() ) {
 223+ return 'stabilize_expiry_old';
 224+ }
 225+ }
 226+ # Update the DB row with the new config...
 227+ $changed = $this->updateConfigRow( $reset );
 228+ # Log if this actually changed anything...
 229+ if ( $changed ) {
 230+ # Update logs and make a null edit
 231+ $nullRev = $this->updateLogsAndHistory( $reset );
 232+ # Null edit may have been autoreviewed already
 233+ $frev = FlaggedRevision::newFromTitle( $this->page, $nullRev->getId(), FR_MASTER );
 234+ # We may need to invalidate the page links after changing the stable version.
 235+ # Only do so if not already done, such as by an auto-review of the null edit.
 236+ $invalidate = !$frev;
 237+ # Check if this null edit is to be reviewed...
 238+ if ( !$frev && $this->reviewThis ) {
 239+ $flags = null;
 240+ $article = new Article( $this->page );
 241+ # Review this revision of the page...
 242+ $ok = FlaggedRevs::autoReviewEdit(
 243+ $article, $wgUser, $nullRev->getText(), $nullRev, $flags, true );
 244+ if( $ok ) {
 245+ FlaggedRevs::markRevisionPatrolled( $nullRev ); // reviewed -> patrolled
 246+ $invalidate = false; // links invalidated (with auto-reviewed)
 247+ }
 248+ }
 249+ # Update the links tables as the stable version may now be the default page...
 250+ if ( $invalidate ) {
 251+ FlaggedRevs::titleLinksUpdate( $this->page );
 252+ }
 253+ }
 254+ # Apply watchlist checkbox value (may be NULL)
 255+ $this->updateWatchlist();
 256+ # Take this opportunity to purge out expired configurations
 257+ FlaggedRevs::purgeExpiredConfigurations();
 258+ return true;
 259+ }
 260+
 261+ /*
 262+ * Do history & log updates:
 263+ * (a) Add a new stability log entry
 264+ * (b) Add a null edit like the log entry
 265+ * @return Revision
 266+ */
 267+ protected function updateLogsAndHistory( $reset ) {
 268+ global $wgContLang;
 269+ $article = new Article( $this->page );
 270+ $latest = $this->page->getLatestRevID( GAID_FOR_UPDATE );
 271+ # Config may have changed to allow stable versions.
 272+ # Refresh tracking to account for any hidden reviewed versions...
 273+ $frev = FlaggedRevision::newFromStable( $this->page, FR_MASTER );
 274+ if ( $frev ) {
 275+ FlaggedRevs::updateStableVersion( $article, $frev->getRevision(), $latest );
 276+ } else {
 277+ FlaggedRevs::clearTrackingRows( $article->getId() );
 278+ }
 279+ # Insert stability log entry...
 280+ $log = new LogPage( 'stable' );
 281+ if ( $reset ) {
 282+ $log->addEntry( 'reset', $this->page, $this->reason );
 283+ $type = "stable-logentry-reset";
 284+ $settings = ''; // no level, expiry info
 285+ } else {
 286+ $params = $this->getLogParams();
 287+ $log->addEntry( 'config', $this->page, $this->reason,
 288+ FlaggedRevsLogs::collapseParams( $params ) );
 289+ $type = "stable-logentry-config";
 290+ // Settings message in text form (e.g. [x=a,y=b,z])
 291+ $settings = FlaggedRevsLogs::stabilitySettings( $params, true /*content*/ );
 292+ }
 293+ # Build null-edit comment...<action: reason [settings] (expiry)>
 294+ $comment = $wgContLang->ucfirst(
 295+ wfMsgForContent( $type, $this->page->getPrefixedText() ) ); // action
 296+ if ( $this->reason != '' ) {
 297+ $comment .= wfMsgForContent( 'colon-separator' ) . $this->reason; // add reason
 298+ }
 299+ if ( $settings != '' ) {
 300+ $comment .= " {$settings}"; // add settings
 301+ }
 302+ # Insert a null revision...
 303+ $dbw = wfGetDB( DB_MASTER );
 304+ $nullRev = Revision::newNullRevision( $dbw, $article->getId(), $comment, true );
 305+ $nullRevId = $nullRev->insertOn( $dbw );
 306+ # Update page record and touch page
 307+ $article->updateRevisionOn( $dbw, $nullRev, $latest );
 308+ wfRunHooks( 'NewRevisionFromEditComplete', array( $article, $nullRev, $latest ) );
 309+ # Return null Revision object for autoreview check
 310+ return $nullRev;
 311+ }
 312+
 313+ /*
 314+ * Checks if new config is the same as the site default
 315+ * @return bool
 316+ */
 317+ protected function newConfigIsReset() {
 318+ return false;
 319+ }
 320+
 321+ /*
 322+ * Get assoc. array of log params
 323+ * @return array
 324+ */
 325+ protected function getLogParams() {
 326+ return array();
 327+ }
 328+
 329+ /*
 330+ * (a) Watch page if $watchThis is true
 331+ * (b) Unwatch if $watchThis is false
 332+ */
 333+ protected function updateWatchlist() {
 334+ global $wgUser;
 335+ # Apply watchlist checkbox value (may be NULL)
 336+ if ( $this->watchThis === true ) {
 337+ $wgUser->addWatch( $this->page );
 338+ } elseif ( $this->watchThis === false ) {
 339+ $wgUser->removeWatch( $this->page );
 340+ }
 341+ }
 342+
 343+ protected function loadExpiry() {
 344+ # Custom expiry takes precedence
 345+ if ( $this->expiry == '' ) {
 346+ $this->expiry = $this->expirySelection;
 347+ if ( $this->expiry == 'existing' ) {
 348+ $this->expiry = $this->oldExpiry;
 349+ }
 350+ }
 351+ }
 352+
 353+ protected function loadReason() {
 354+ # Custom reason takes precedence
 355+ if ( $this->reasonSelection != 'other' ) {
 356+ $comment = $this->reasonSelection; // start with dropdown reason
 357+ if ( $this->reason != '' ) {
 358+ # Append custom reason
 359+ $comment .= wfMsgForContent( 'colon-separator' ) . $this->reason;
 360+ }
 361+ } else {
 362+ $comment = $this->reason; // just use custom reason
 363+ }
 364+ $this->reason = $comment;
 365+ }
 366+
 367+ // Same JS used for expiry for either $wgFlaggedRevsProtection case
 368+ public static function addProtectionJS() {
 369+ global $wgOut;
 370+ $wgOut->addScript(
 371+ "<script type=\"text/javascript\">
 372+ function onFRChangeExpiryDropdown() {
 373+ document.getElementById('mwStabilizeExpiryOther').value = '';
 374+ }
 375+ function onFRChangeExpiryField() {
 376+ document.getElementById('mwStabilizeExpirySelection').value = 'othertime';
 377+ }
 378+ </script>"
 379+ );
 380+ }
 381+}
 382+
 383+// Assumes $wgFlaggedRevsProtection is off
 384+class PageStabilityForm extends FlaggedRevsConfigForm {
 385+ /* Form parameters which can be user given */
 386+ public $select = -1; # Precedence
 387+
 388+ public function getReviewThis() {
 389+ return $this->reviewThis;
 390+ }
 391+
 392+ public function setReviewThis( $value ) {
 393+ $this->trySet( $this->reviewThis, $value );
 394+ }
 395+
 396+ public function getPrecedence() {
 397+ return $this->select;
 398+ }
 399+
 400+ public function setPrecedence( $value ) {
 401+ $this->trySet( $this->select, $value );
 402+ }
 403+
 404+ public function getOverride() {
 405+ return $this->override;
 406+ }
 407+
 408+ public function setOverride( $value ) {
 409+ $this->trySet( $this->override, $value );
 410+ }
 411+
 412+ public function handlePostedParams() {
 413+ $this->loadReason();
 414+ $this->loadExpiry();
 415+ $this->override = $this->override ? 1 : 0; // default version settings is 0 or 1
 416+ if ( !FlaggedRevs::isValidPrecedence( $this->select ) ) {
 417+ return 'stabilize_invalid_precedence'; // invalid precedence value
 418+ }
 419+ // Check autoreview restriction setting
 420+ if ( !FlaggedRevs::userCanSetAutoreviewLevel( $this->autoreview ) ) {
 421+ return 'stabilize_invalid_autoreview'; // invalid value
 422+ }
 423+ return true;
 424+ }
 425+
 426+ protected function getLogParams() {
 427+ return array(
 428+ 'override' => $this->override,
 429+ 'autoreview' => $this->autoreview,
 430+ 'expiry' => $this->expiry, // TS_MW/infinity
 431+ 'precedence' => $this->select
 432+ );
 433+ }
 434+
 435+ // Return current config array
 436+ public function getOldConfig() {
 437+ if ( $this->page === false ) {
 438+ $this->handleParams(); // handleParams() not called first
 439+ }
 440+ return $this->oldConfig;
 441+ }
 442+
 443+ protected function preloadSettings() {
 444+ # Get visiblity settings...
 445+ $this->select = $this->oldConfig['select'];
 446+ $this->override = $this->oldConfig['override'];
 447+ # Get autoreview restrictions...
 448+ $this->autoreview = $this->oldConfig['autoreview'];
 449+ return true;
 450+ }
 451+
 452+ // returns whether row changed
 453+ protected function updateConfigRow( $reset ) {
 454+ $changed = false;
 455+ $dbw = wfGetDB( DB_MASTER );
 456+ # If setting to site default values and there is a row then erase it
 457+ if ( $reset ) {
 458+ $dbw->delete( 'flaggedpage_config',
 459+ array( 'fpc_page_id' => $this->page->getArticleID() ),
 460+ __METHOD__
 461+ );
 462+ $changed = ( $dbw->affectedRows() != 0 ); // did this do anything?
 463+ # Otherwise, add/replace row if we are not just setting it to the site default
 464+ } elseif ( !$reset ) {
 465+ $dbExpiry = Block::encodeExpiry( $this->expiry, $dbw );
 466+ # Get current config...
 467+ $oldRow = $dbw->selectRow( 'flaggedpage_config',
 468+ array( 'fpc_select', 'fpc_override', 'fpc_level', 'fpc_expiry' ),
 469+ array( 'fpc_page_id' => $this->page->getArticleID() ),
 470+ __METHOD__,
 471+ 'FOR UPDATE'
 472+ );
 473+ # Check if this is not the same config as the existing row (if any)
 474+ $changed = self::configIsDifferent( $oldRow,
 475+ $this->select, $this->override, $this->autoreview, $dbExpiry );
 476+ # If the new config is different, replace the old row...
 477+ if ( $changed ) {
 478+ $dbw->replace( 'flaggedpage_config',
 479+ array( 'PRIMARY' ),
 480+ array(
 481+ 'fpc_page_id' => $this->page->getArticleID(),
 482+ 'fpc_select' => (int)$this->select,
 483+ 'fpc_override' => (int)$this->override,
 484+ 'fpc_level' => $this->autoreview,
 485+ 'fpc_expiry' => $dbExpiry
 486+ ),
 487+ __METHOD__
 488+ );
 489+ }
 490+ }
 491+ return $changed;
 492+ }
 493+
 494+ protected function newConfigIsReset() {
 495+ return ( $this->select == FlaggedRevs::getPrecedence()
 496+ && $this->override == FlaggedRevs::isStableShownByDefault()
 497+ && $this->autoreview == '' );
 498+ }
 499+
 500+ // Checks if new config is different than the existing row
 501+ protected function configIsDifferent( $oldRow, $select, $override, $autoreview, $dbExpiry ) {
 502+ if( !$oldRow ) {
 503+ return true; // no previous config
 504+ }
 505+ return ( $oldRow->fpc_select != $select // ...precedence changed, or...
 506+ || $oldRow->fpc_override != $override // ...override changed, or...
 507+ || $oldRow->fpc_level != $autoreview // ...autoreview level changed, or...
 508+ || $oldRow->fpc_expiry != $dbExpiry // ...expiry changed
 509+ );
 510+ }
 511+}
 512+
 513+// Assumes $wgFlaggedRevsProtection is on
 514+class PageStabilityProtectForm extends FlaggedRevsConfigForm {
 515+ public function handlePostedParams() {
 516+ $this->loadReason();
 517+ $this->loadExpiry();
 518+ # Autoreview only when protecting currently unprotected pages
 519+ $this->reviewThis = ( FlaggedRevs::getProtectionLevel( $this->oldConfig ) == 'none' );
 520+ # Check autoreview restriction setting
 521+ if ( !FlaggedRevs::userCanSetAutoreviewLevel( $this->autoreview ) ) {
 522+ return 'stabilize_invalid_level'; // invalid value
 523+ }
 524+ # Autoreview restriction => use stable
 525+ # No autoreview restriction => site default
 526+ $this->override = ( $this->autoreview != '' )
 527+ ? 1 // edits require review before being published
 528+ : (int)FlaggedRevs::isStableShownByDefault(); // site default
 529+ # Check that settings are a valid protection level...
 530+ $newConfig = array(
 531+ 'override' => $this->override,
 532+ 'autoreview' => $this->autoreview
 533+ );
 534+ if ( FlaggedRevs::getProtectionLevel( $newConfig ) == 'invalid' ) {
 535+ return 'stabilize_invalid_level'; // double-check configuration
 536+ }
 537+ return true;
 538+ }
 539+
 540+ // Doesn't include 'precedence'; checked in FlaggedRevsLogs
 541+ protected function getLogParams() {
 542+ return array(
 543+ 'override' => $this->override, // in case of site changes
 544+ 'autoreview' => $this->autoreview,
 545+ 'expiry' => $this->expiry // TS_MW/infinity
 546+ );
 547+ }
 548+
 549+ protected function preloadSettings() {
 550+ # Get autoreview restrictions...
 551+ $this->autoreview = $this->oldConfig['autoreview'];
 552+ }
 553+
 554+ protected function updateConfigRow( $reset ) {
 555+ $changed = false;
 556+ $dbw = wfGetDB( DB_MASTER );
 557+ # If setting to site default values and there is a row then erase it
 558+ if ( $reset ) {
 559+ $dbw->delete( 'flaggedpage_config',
 560+ array( 'fpc_page_id' => $this->page->getArticleID() ),
 561+ __METHOD__
 562+ );
 563+ $changed = ( $dbw->affectedRows() != 0 ); // did this do anything?
 564+ # Otherwise, add/replace row if we are not just setting it to the site default
 565+ } elseif ( !$reset ) {
 566+ $dbExpiry = Block::encodeExpiry( $this->expiry, $dbw );
 567+ # Get current config...
 568+ $oldRow = $dbw->selectRow( 'flaggedpage_config',
 569+ array( 'fpc_override', 'fpc_level', 'fpc_expiry' ),
 570+ array( 'fpc_page_id' => $this->page->getArticleID() ),
 571+ __METHOD__,
 572+ 'FOR UPDATE'
 573+ );
 574+ # Check if this is not the same config as the existing row (if any)
 575+ $changed = self::configIsDifferent( $oldRow,
 576+ $this->override, $this->autoreview, $dbExpiry );
 577+ # If the new config is different, replace the old row...
 578+ if ( $changed ) {
 579+ $dbw->replace( 'flaggedpage_config',
 580+ array( 'PRIMARY' ),
 581+ array(
 582+ 'fpc_page_id' => $this->page->getArticleID(),
 583+ 'fpc_select' => -1, // ignored
 584+ 'fpc_override' => (int)$this->override,
 585+ 'fpc_level' => $this->autoreview,
 586+ 'fpc_expiry' => $dbExpiry
 587+ ),
 588+ __METHOD__
 589+ );
 590+ }
 591+ }
 592+ return $changed;
 593+ }
 594+
 595+ protected function newConfigIsReset() {
 596+ # For protection config, just ignore the fpc_select column
 597+ return ( $this->autoreview == '' );
 598+ }
 599+
 600+ // Checks if new config is different than the existing row
 601+ protected function configIsDifferent( $oldRow, $override, $autoreview, $dbExpiry ) {
 602+ if( !$oldRow ) {
 603+ return true; // no previous config
 604+ }
 605+ # For protection config, just ignore the fpc_select column
 606+ return ( $oldRow->fpc_override != $override // ...override changed, or...
 607+ || $oldRow->fpc_level != $autoreview // ...autoreview level changed, or...
 608+ || $oldRow->fpc_expiry != $dbExpiry // ...expiry changed
 609+ );
 610+ }
 611+}
\ No newline at end of file
Property changes on: trunk/extensions/FlaggedRevs/forms/FlaggedRevsConfigForm.php
___________________________________________________________________
Name: svn:eol-style
1612 + native
Index: trunk/extensions/FlaggedRevs/specialpages/Stabilization_body.php
@@ -4,8 +4,11 @@
55 exit( 1 );
66 }
77
 8+// Assumes $wgFlaggedRevsProtection is off
89 class Stabilization extends UnlistedSpecialPage
910 {
 11+ protected $form = null;
 12+
1013 public function __construct() {
1114 parent::__construct( 'Stabilization', 'stablesettings' );
1215 }
@@ -13,16 +16,15 @@
1417 public function execute( $par ) {
1518 global $wgRequest, $wgUser, $wgOut;
1619 # Check user token
17 - $confirm = $wgRequest->wasPosted() &&
18 - $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
19 - # Allow unprivileged users to at least view the settings
20 - $this->isAllowed = $wgUser->isAllowed( 'stablesettings' );
 20+ $confirmed = false;
2121 # Let anyone view, but not submit...
2222 if ( $wgRequest->wasPosted() ) {
23 - if ( $wgUser->isBlocked( !$confirm ) ) {
 23+ # Check user token
 24+ $confirmed = $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
 25+ if ( $wgUser->isBlocked( !$confirmed ) ) {
2426 $wgOut->blockedPage();
2527 return;
26 - } elseif ( !$this->isAllowed ) {
 28+ } elseif ( !$wgUser->isAllowed( 'stablesettings' ) ) {
2729 $wgOut->permissionRequired( 'stablesettings' );
2830 return;
2931 } elseif ( wfReadOnly() ) {
@@ -32,191 +34,98 @@
3335 }
3436 # Set page title
3537 $this->setHeaders();
 38+ $this->sk = $wgUser->getSkin();
3639
37 - $this->skin = $wgUser->getSkin();
 40+ $this->form = new PageStabilityForm();
 41+ $form = $this->form; // convenience
3842 # Our target page
39 - $this->target = $wgRequest->getVal( 'page', $par );
 43+ $form->setTarget( $wgRequest->getVal( 'page', $par ) );
4044 # Watch checkbox
41 - $this->watchThis = (bool)$wgRequest->getCheck( 'wpWatchthis' );
 45+ $form->setWatchThis( (bool)$wgRequest->getCheck( 'wpWatchthis' ) );
4246 # Reason
43 - $this->reason = $wgRequest->getText( 'wpReason' );
44 - $this->reasonSelection = $wgRequest->getVal( 'wpReasonSelection' );
 47+ $form->setReason( $wgRequest->getText( 'wpReason' ) );
 48+ $form->setReasonSelection( $wgRequest->getVal( 'wpReasonSelection' ) );
4549 # Expiry
46 - $this->expiry = $wgRequest->getText( 'mwStabilize-expiry' );
47 - $this->expirySelection = $wgRequest->getVal( 'wpExpirySelection' );
 50+ $form->setExpiry( $wgRequest->getText( 'mwStabilize-expiry' ) );
 51+ $form->setExpirySelection( $wgRequest->getVal( 'wpExpirySelection' ) );
4852 # Precedence
49 - $this->select = $wgRequest->getInt( 'wpStableconfig-select' );
50 - $this->override = (int)$wgRequest->getBool( 'wpStableconfig-override' );
 53+ $form->setPrecedence( $wgRequest->getInt( 'wpStableconfig-select' ) );
 54+ $form->setOverride( (int)$wgRequest->getBool( 'wpStableconfig-override' ) );
5155 # Get autoreview restrictions...
52 - $this->autoreview = $wgRequest->getVal( 'mwProtect-level-autoreview' );
 56+ $form->setAutoreview( $wgRequest->getVal( 'mwProtect-level-autoreview' ) );
5357 # Get auto-review option...
54 - $this->reviewThis = $wgRequest->getBool( 'wpReviewthis', true );
55 - $this->wasPosted = $wgRequest->wasPosted();
 58+ $form->setReviewThis( $wgRequest->getBool( 'wpReviewthis', true ) );
 59+ $form->setWasPosted( $wgRequest->wasPosted() );
5660
5761 # Fill in & validate some parameters
58 - $isValid = $this->handleParams();
 62+ $status = $form->handleParams();
 63+ $title = $form->getPage(); // convenience
5964
60 - # We need a page...
61 - if ( is_null( $this->page ) ) {
 65+ # We need a valid, existing, page...
 66+ if ( $status === 'stabilize_page_invalid' ) {
6267 $wgOut->showErrorPage( 'notargettitle', 'notargettext' );
6368 return;
64 - } elseif ( !$this->page->exists() ) {
 69+ } elseif ( $status === 'stabilize_page_notexists' ) {
6570 $wgOut->addWikiText(
66 - wfMsg( 'stabilization-notexists', $this->page->getPrefixedText() ) );
 71+ wfMsg( 'stabilization-notexists', $title->getPrefixedText() ) );
6772 return;
68 - } elseif ( !FlaggedRevs::inReviewNamespace( $this->page ) ) {
 73+ } elseif ( $status === 'stabilize_page_unreviewable' ) {
6974 $wgOut->addWikiText(
70 - wfMsg( 'stabilization-notcontent', $this->page->getPrefixedText() ) );
 75+ wfMsg( 'stabilization-notcontent', $title->getPrefixedText() ) );
7176 return;
7277 }
73 - # Users who cannot edit or review the page cannot set this
74 - if ( !$this->page->userCan( 'edit' ) || !$this->page->userCan( 'review' ) ) {
75 - $this->isAllowed = false;
76 - }
7778
78 - # Disable some elements as needed
79 - $this->disabledAttrib = $this->isAllowed ?
80 - array() : array( 'disabled' => 'disabled' );
8179 # Show form or submit...
82 - if ( $this->isAllowed && $isValid && $confirm ) {
83 - $status = $this->submit();
 80+ if ( $form->isAllowed() && $status === true && $confirmed ) {
 81+ $status = $form->submit();
8482 if ( $status === true ) {
85 - $wgOut->redirect( $this->page->getFullUrl() );
 83+ $wgOut->redirect( $title->getFullUrl() );
8684 } else {
87 - $this->showSettings( wfMsg( $status ) );
 85+ $this->showForm( wfMsg( $status ) );
8886 }
8987 } else {
90 - $this->showSettings();
 88+ $this->showForm();
9189 }
9290 }
9391
94 - /**
95 - * Verify and clean up parameters and preload data from DB.
96 - * Note: if false is returned items may not all be set.
97 - * TODO: return error keywords?
98 - * @return bool success
99 - */
100 - public function handleParams() {
101 - $this->page = Title::newFromURL( $this->target );
102 - if ( is_null( $this->page ) ) {
103 - return false; // page title is invalid
104 - }
105 - # Get the current page config and GMT expiry
106 - $this->config = FlaggedRevs::getPageVisibilitySettings( $this->page, FR_MASTER );
107 - $this->oldExpiry = $this->config['expiry'] === 'infinity'
108 - ? 'infinite'
109 - : wfTimestamp( TS_RFC2822, $this->config['expiry'] );
110 - # Handle views (GET)
111 - if ( !$this->wasPosted ) {
112 - # Fill in existing settings
113 - $this->preloadSettings( $this->config );
114 - # Handle submission data (POST)
115 - } else {
116 - $this->loadReason();
117 - $this->loadExpiry();
118 - // Protection level case...
119 - if ( FlaggedRevs::useProtectionLevels() ) {
120 - # Autoreview restriction => use stable
121 - # No autoreview restriction => site default
122 - $this->override = ( $this->autoreview != '' )
123 - ? 1 // edits require review before being published
124 - : (int)FlaggedRevs::isStableShownByDefault();
125 - # Leave the selection precedence to the site default
126 - $this->select = FlaggedRevs::getPrecedence();
127 - # Autoreview only when protecting currently unprotected pages
128 - $this->reviewThis = ( FlaggedRevs::getProtectionLevel( $this->config ) == 'none' );
129 - # Check that settings are a valid protection level...
130 - $newConfig = array(
131 - 'override' => $this->override,
132 - 'autoreview' => $this->autoreview
133 - );
134 - if ( FlaggedRevs::getProtectionLevel( $newConfig ) == 'invalid' ) {
135 - return false; // this is not a valid configuration
136 - }
137 - // General case...
138 - } else {
139 - if ( $this->override !== 0 && $this->override !== 1 ) {
140 - return false; // default version settings is 0 or 1
141 - }
142 - if ( !FlaggedRevs::isValidPrecedence( $this->select ) ) {
143 - return false; // invalid precedence value
144 - }
145 - // Check autoreview restriction setting
146 - if ( !FlaggedRevs::userCanSetAutoreviewLevel( $this->autoreview ) ) {
147 - return false; // invalid value
148 - }
149 - }
150 - }
151 - return true;
152 - }
153 -
154 - private function preloadSettings( $config ) {
155 - # Get visiblity settings...
156 - $this->select = $config['select'];
157 - $this->override = $config['override'];
158 - # Get autoreview restrictions...
159 - $this->autoreview = $config['autoreview'];
160 - }
161 -
162 - private function loadExpiry() {
163 - // Custom expiry takes precedence
164 - if ( $this->expiry == '' ) {
165 - $this->expiry = $this->expirySelection;
166 - if ( $this->expiry == 'existing' ) {
167 - $this->expiry = $this->oldExpiry;
168 - }
169 - }
170 - }
171 -
172 - private function loadReason() {
173 - // Custom reason takes precedence
174 - if ( $this->reasonSelection != 'other' ) {
175 - $comment = $this->reasonSelection; // start with dropdown reason
176 - if ( $this->reason != '' ) {
177 - // Append custom reason
178 - $comment .= wfMsgForContent( 'colon-separator' ) . $this->reason;
179 - }
180 - } else {
181 - $comment = $this->reason; // just use custom reason
182 - }
183 - $this->reason = $comment;
184 - }
185 -
186 - protected function showSettings( $err = null ) {
 92+ public function showForm( $err = null ) {
18793 global $wgOut, $wgLang, $wgUser;
 94+ $form = $this->form; // convenience
 95+ $title = $this->form->getPage();
 96+ $oldConfig = $form->getOldConfig();
 97+
 98+ $s = ''; // form HTML string
18899 # Add any error messages
189100 if ( "" != $err ) {
190101 $wgOut->setSubtitle( wfMsgHtml( 'formerror' ) );
191102 $wgOut->addHTML( "<p class='error'>{$err}</p>\n" );
192103 }
193104 # Add header text
194 - if ( !$this->isAllowed ) {
195 - $form = wfMsgExt( 'stabilization-perm', array( 'parse' ),
196 - $this->page->getPrefixedText() );
 105+ if ( !$form->isAllowed() ) {
 106+ $s .= wfMsgExt( 'stabilization-perm', 'parse', $title->getPrefixedText() );
197107 } else {
198 - $form = wfMsgExt( 'stabilization-text', array( 'parse' ),
199 - $this->page->getPrefixedText() );
 108+ $s .= wfMsgExt( 'stabilization-text', 'parse', $title->getPrefixedText() );
200109 }
201110 # Borrow some protection messages for dropdowns
202111 $reasonDropDown = Xml::listDropDown( 'wpReasonSelection',
203112 wfMsgForContent( 'protect-dropdown' ),
204113 wfMsgForContent( 'protect-otherreason-op' ),
205 - $this->reasonSelection,
 114+ $form->getReasonSelection(),
206115 'mwStabilize-reason', 4
207116 );
208117 $scExpiryOptions = wfMsgForContent( 'protect-expiry-options' );
209 - $showProtectOptions = ( $scExpiryOptions !== '-' && $this->isAllowed );
 118+ $showProtectOptions = ( $scExpiryOptions !== '-' && $form->isAllowed() );
210119 # Add the current expiry as an option
211120 $expiryFormOptions = '';
212 - if ( $this->config['expiry'] && $this->config['expiry'] != 'infinity' ) {
213 - $timestamp = $wgLang->timeanddate( $this->config['expiry'] );
214 - $d = $wgLang->date( $this->config['expiry'] );
215 - $t = $wgLang->time( $this->config['expiry'] );
 121+ if ( $oldConfig['expiry'] && $oldConfig['expiry'] != 'infinity' ) {
 122+ $timestamp = $wgLang->timeanddate( $oldConfig['expiry'] );
 123+ $d = $wgLang->date( $oldConfig['expiry'] );
 124+ $t = $wgLang->time( $oldConfig['expiry'] );
216125 $expiryFormOptions .=
217126 Xml::option(
218127 wfMsg( 'protect-existing-expiry', $timestamp, $d, $t ),
219128 'existing',
220 - $this->config['expiry'] == 'existing'
 129+ $oldConfig['expiry'] == 'existing'
221130 ) . "\n";
222131 }
223132 $expiryFormOptions .= Xml::option( wfMsg( 'protect-othertime-op' ), "othertime" ) . "\n";
@@ -229,41 +138,46 @@
230139 }
231140 $show = htmlspecialchars( $show );
232141 $value = htmlspecialchars( $value );
233 - $expiryFormOptions .= Xml::option( $show, $value,
234 - $this->config['expiry'] === $value ) . "\n";
 142+ $expiryFormOptions .= Xml::option( $show, $value, $oldConfig['expiry'] === $value );
 143+ $expiryFormOptions .= "\n";
235144 }
236145 # Add stable version override and selection options
237146 $special = SpecialPage::getTitleFor( 'Stabilization' );
238 - $form .= Xml::openElement( 'form', array( 'name' => 'stabilization',
239 - 'action' => $special->getLocalUrl(), 'method' => 'post' ) ) .
 147+ $s .= Xml::openElement( 'form', array( 'name' => 'stabilization',
 148+ 'action' => $special->getLocalUrl(), 'method' => 'post' ) );
 149+ $s .=
240150 Xml::fieldset( wfMsg( 'stabilization-def' ), false ) . "\n" .
241151 Xml::radioLabel( wfMsg( 'stabilization-def1' ), 'wpStableconfig-override', 1,
242 - 'default-stable', 1 == $this->override, $this->disabledAttrib ) . '<br />' . "\n" .
 152+ 'default-stable', 1 == $form->getOverride(), $this->disabledAttr() ) .
 153+ '<br />' . "\n" .
243154 Xml::radioLabel( wfMsg( 'stabilization-def2' ), 'wpStableconfig-override', 0,
244 - 'default-current', 0 == $this->override, $this->disabledAttrib ) . "\n" .
 155+ 'default-current', 0 == $form->getOverride(), $this->disabledAttr() ) . "\n" .
245156 Xml::closeElement( 'fieldset' ) .
246157
247158 Xml::fieldset( wfMsg( 'stabilization-select' ), false ) .
248159 Xml::radioLabel( wfMsg( 'stabilization-select3' ), 'wpStableconfig-select',
249 - FLAGGED_VIS_PRISTINE, 'stable-select3', FLAGGED_VIS_PRISTINE == $this->select,
250 - $this->disabledAttrib ) . '<br />' . "\n" .
 160+ FLAGGED_VIS_PRISTINE, 'stable-select3',
 161+ FLAGGED_VIS_PRISTINE == $form->getPrecedence(),
 162+ $this->disabledAttr() ) . '<br />' . "\n" .
251163 Xml::radioLabel( wfMsg( 'stabilization-select1' ), 'wpStableconfig-select',
252 - FLAGGED_VIS_QUALITY, 'stable-select1', FLAGGED_VIS_QUALITY == $this->select,
253 - $this->disabledAttrib ) . '<br />' . "\n" .
 164+ FLAGGED_VIS_QUALITY, 'stable-select1',
 165+ FLAGGED_VIS_QUALITY == $form->getPrecedence(),
 166+ $this->disabledAttr() ) . '<br />' . "\n" .
254167 Xml::radioLabel( wfMsg( 'stabilization-select2' ), 'wpStableconfig-select',
255 - FLAGGED_VIS_LATEST, 'stable-select2', FLAGGED_VIS_LATEST == $this->select,
256 - $this->disabledAttrib ) . '<br />' . "\n" .
 168+ FLAGGED_VIS_LATEST, 'stable-select2',
 169+ FLAGGED_VIS_LATEST == $form->getPrecedence(),
 170+ $this->disabledAttr() ) . '<br />' . "\n" .
257171 Xml::closeElement( 'fieldset' );
258172 # Add autoreview restriction select
259 - $form .= Xml::fieldset( wfMsg( 'stabilization-restrict' ), false ) .
260 - $this->buildSelector( $this->autoreview ) .
 173+ $s .= Xml::fieldset( wfMsg( 'stabilization-restrict' ), false ) .
 174+ $this->buildSelector( $form->getAutoreview() ) .
261175 Xml::closeElement( 'fieldset' ) .
262176
263177 Xml::fieldset( wfMsg( 'stabilization-leg' ), false ) .
264178 Xml::openElement( 'table' );
265179 # Add expiry dropdown
266 - if ( $showProtectOptions && $this->isAllowed ) {
267 - $form .= "
 180+ if ( $showProtectOptions && $form->isAllowed() ) {
 181+ $s .= "
268182 <tr>
269183 <td class='mw-label'>" .
270184 Xml::label( wfMsg( 'stabilization-expiry' ), 'mwStabilizeExpirySelection' ) .
@@ -274,34 +188,35 @@
275189 'id' => 'mwStabilizeExpirySelection',
276190 'name' => 'wpExpirySelection',
277191 'onchange' => 'onFRChangeExpiryDropdown()',
278 - ) + $this->disabledAttrib,
 192+ ) + $this->disabledAttr(),
279193 $expiryFormOptions ) .
280194 "</td>
281195 </tr>";
282196 }
283197 # Add custom expiry field
284198 $attribs = array( 'id' => "mwStabilizeExpiryOther",
285 - 'onkeyup' => 'onFRChangeExpiryField()' ) + $this->disabledAttrib;
286 - $form .= "
 199+ 'onkeyup' => 'onFRChangeExpiryField()' ) + $this->disabledAttr();
 200+ $formExpiry = $form->getExpiry() ?
 201+ $form->getExpiry() : $form->getOldExpiryGMT();
 202+ $s .= "
287203 <tr>
288204 <td class='mw-label'>" .
289205 Xml::label( wfMsg( 'stabilization-othertime' ), 'mwStabilizeExpiryOther' ) .
290206 '</td>
291207 <td class="mw-input">' .
292 - Xml::input( "mwStabilize-expiry", 50,
293 - $this->expiry ? $this->expiry : $this->oldExpiry, $attribs ) .
 208+ Xml::input( "mwStabilize-expiry", 50, $formExpiry, $attribs ) .
294209 '</td>
295210 </tr>';
296211 # Add comment input and submit button
297 - if ( $this->isAllowed ) {
 212+ if ( $form->isAllowed() ) {
298213 $watchLabel = wfMsgExt( 'watchthis', array( 'parseinline' ) );
299214 $watchAttribs = array( 'accesskey' => wfMsg( 'accesskey-watch' ),
300215 'id' => 'wpWatchthis' );
301216 $watchChecked = ( $wgUser->getOption( 'watchdefault' )
302 - || $this->page->userIsWatching() );
 217+ || $title->userIsWatching() );
303218 $reviewLabel = wfMsgExt( 'stabilization-review', array( 'parseinline' ) );
304219
305 - $form .= ' <tr>
 220+ $s .= ' <tr>
306221 <td class="mw-label">' .
307222 xml::label( wfMsg( 'stabilization-comment' ), 'wpReasonSelection' ) .
308223 '</td>
@@ -314,18 +229,18 @@
315230 Xml::label( wfMsg( 'stabilization-otherreason' ), 'wpReason' ) .
316231 '</td>
317232 <td class="mw-input">' .
318 - Xml::input( 'wpReason', 70, $this->reason, array( 'id' => 'wpReason' ) ) .
 233+ Xml::input( 'wpReason', 70, $form->getReason(), array( 'id' => 'wpReason' ) ) .
319234 '</td>
320235 </tr>
321236 <tr>
322237 <td></td>
323238 <td class="mw-input">' .
324 - Xml::check( 'wpReviewthis', $this->reviewThis,
 239+ Xml::check( 'wpReviewthis', $form->getReviewThis(),
325240 array( 'id' => 'wpReviewthis' ) ) .
326241 "<label for='wpReviewthis'>{$reviewLabel}</label>" .
327242 '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' .
328243 Xml::check( 'wpWatchthis', $watchChecked, $watchAttribs ) .
329 - "<label for='wpWatchthis'" . $this->skin->tooltipAndAccesskey( 'watch' ) .
 244+ "<label for='wpWatchthis'" . $this->sk->tooltipAndAccesskey( 'watch' ) .
330245 ">{$watchLabel}</label>" .
331246 '</td>
332247 </tr>
@@ -336,46 +251,33 @@
337252 '</td>
338253 </tr>' . Xml::closeElement( 'table' ) .
339254 Xml::hidden( 'title', $this->getTitle()->getPrefixedDBKey() ) .
340 - Xml::hidden( 'page', $this->page->getPrefixedText() ) .
 255+ Xml::hidden( 'page', $title->getPrefixedText() ) .
341256 Xml::hidden( 'wpEditToken', $wgUser->editToken() );
342257 } else {
343 - $form .= Xml::closeElement( 'table' );
 258+ $s .= Xml::closeElement( 'table' );
344259 }
345 - $form .= Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' );
 260+ $s .= Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' );
346261
347 - $wgOut->addHTML( $form );
 262+ $wgOut->addHTML( $s );
348263
349264 $wgOut->addHTML( Xml::element( 'h2', null,
350265 htmlspecialchars( LogPage::logName( 'stable' ) ) ) );
351 - LogEventsList::showLogExtract( $wgOut, 'stable', $this->page->getPrefixedText() );
 266+ LogEventsList::showLogExtract( $wgOut, 'stable', $title->getPrefixedText() );
352267
353 - # Add some script for expiry dropdowns
354 - self::addProtectionJS();
 268+ # Add some javascript for expiry dropdowns
 269+ PageStabilityForm::addProtectionJS();
355270 }
356271
357 - public static function addProtectionJS() {
358 - global $wgOut;
359 - $wgOut->addScript(
360 - "<script type=\"text/javascript\">
361 - function onFRChangeExpiryDropdown() {
362 - document.getElementById('mwStabilizeExpiryOther').value = '';
363 - }
364 - function onFRChangeExpiryField() {
365 - document.getElementById('mwStabilizeExpirySelection').value = 'othertime';
366 - }
367 - </script>"
368 - );
369 - }
370 -
371272 protected function buildSelector( $selected ) {
372 - global $wgUser;
373273 $allowedLevels = array();
374274 $levels = FlaggedRevs::getRestrictionLevels();
375275 array_unshift( $levels, '' ); // Add a "none" level
376276 foreach ( $levels as $key ) {
377277 # Don't let them choose levels they can't set,
378278 # but *show* them all when the form is disabled.
379 - if ( $this->isAllowed && !FlaggedRevs::userCanSetAutoreviewLevel( $key ) ) {
 279+ if ( $this->form->isAllowed()
 280+ && !FlaggedRevs::userCanSetAutoreviewLevel( $key ) )
 281+ {
380282 continue;
381283 }
382284 $allowedLevels[] = $key;
@@ -385,7 +287,7 @@
386288 'id' => $id,
387289 'name' => $id,
388290 'size' => count( $allowedLevels ),
389 - ) + $this->disabledAttrib;
 291+ ) + $this->disabledAttr();
390292
391293 $out = Xml::openElement( 'select', $attribs );
392294 foreach ( $allowedLevels as $key ) {
@@ -414,183 +316,10 @@
415317 }
416318 }
417319
418 - public function submit() {
419 - global $wgUser, $wgContLang;
420 - # Take this opportunity to purge out expired configurations
421 - FlaggedRevs::purgeExpiredConfigurations();
422 - # Are we are going back to site defaults?
423 - $reset = self::configIsReset( $this->select, $this->override, $this->autoreview );
424 - # Parse and cleanup the expiry time given...
425 - if ( $reset || $this->expiry == 'infinite' || $this->expiry == 'indefinite' ) {
426 - $this->expiry = Block::infinity(); // normalize to 'infinity'
427 - } else {
428 - # Convert GNU-style date, on error returns -1 for PHP <5.1 and false for PHP >=5.1
429 - $this->expiry = strtotime( $this->expiry );
430 - if ( $this->expiry < 0 || $this->expiry === false ) {
431 - return 'stabilize_expiry_invalid';
432 - }
433 - # Convert date to MW timestamp format
434 - $this->expiry = wfTimestamp( TS_MW, $this->expiry );
435 - if ( $this->expiry < wfTimestampNow() ) {
436 - return 'stabilize_expiry_old';
437 - }
438 - }
439 - # Update the DB row with the new config...
440 - $changed = $this->updateConfigRow( $reset );
441 - # Log if this actually changed anything...
442 - if ( $changed ) {
443 - $article = new Article( $this->page );
444 - $latest = $this->page->getLatestRevID( GAID_FOR_UPDATE );
445 - # Config may have changed to allow stable versions.
446 - # Refresh tracking to account for any hidden reviewed versions...
447 - $frev = FlaggedRevision::newFromStable( $this->page, FR_MASTER );
448 - if ( $frev ) {
449 - FlaggedRevs::updateStableVersion( $article, $frev->getRevision(), $latest );
450 - } else {
451 - FlaggedRevs::clearTrackingRows( $article->getId() );
452 - }
453 - # Insert stability log entry...
454 - $log = new LogPage( 'stable' );
455 - if ( $reset ) {
456 - $log->addEntry( 'reset', $this->page, $this->reason );
457 - $type = "stable-logentry-reset";
458 - $settings = ''; // no level, expiry info
459 - } else {
460 - $params = array(
461 - 'override' => $this->override,
462 - 'autoreview' => $this->autoreview,
463 - 'expiry' => $this->expiry // TS_MW/infinity
464 - );
465 - // Precedence unchanged by protection (stabilityLogLinks checks this)
466 - if( !FlaggedRevs::useProtectionLevels() ) {
467 - $params['precedence'] = $this->select;
468 - }
469 - $log->addEntry( 'config', $this->page, $this->reason,
470 - FlaggedRevsLogs::collapseParams( $params ) );
471 - $type = "stable-logentry-config";
472 - $settings = FlaggedRevsLogs::stabilitySettings( $params, true /*content*/ );
473 - }
474 - # Build null-edit comment...<action: reason [settings] (expiry)>
475 - $comment = $wgContLang->ucfirst(
476 - wfMsgForContent( $type, $this->page->getPrefixedText() ) ); // action
477 - if ( $this->reason != '' ) {
478 - $comment .= wfMsgForContent( 'colon-separator' ) . $this->reason; // add reason
479 - }
480 - if ( $settings != '' ) {
481 - $comment .= " {$settings}"; // add settings
482 - }
483 - # Insert a null revision...
484 - $dbw = wfGetDB( DB_MASTER );
485 - $nullRev = Revision::newNullRevision( $dbw, $article->getId(), $comment, true );
486 - $nullRevId = $nullRev->insertOn( $dbw );
487 - # Update page record and touch page
488 - $article->updateRevisionOn( $dbw, $nullRev, $latest );
489 - wfRunHooks( 'NewRevisionFromEditComplete',
490 - array( $article, $nullRev, $latest ) );
491 -
492 - # Null edit may have been autoreviewed already
493 - $frev = FlaggedRevision::newFromTitle( $this->page, $nullRevId, FR_MASTER );
494 - # We may need to invalidate the page links after changing the stable version.
495 - # Only do so if not already done, such as by an auto-review of the null edit.
496 - $invalidate = !$frev;
497 - # Check if this null edit is to be reviewed...
498 - if ( !$frev && $this->reviewThis ) {
499 - $flags = null;
500 - # Review this revision of the page...
501 - $ok = FlaggedRevs::autoReviewEdit(
502 - $article, $wgUser, $nullRev->getText(), $nullRev, $flags, true );
503 - if( $ok ) {
504 - FlaggedRevs::markRevisionPatrolled( $nullRev ); // reviewed -> patrolled
505 - $invalidate = false; // links invalidated (with auto-reviewed)
506 - }
507 - }
508 - # Update the links tables as the stable version may now be the default page...
509 - if ( $invalidate ) {
510 - FlaggedRevs::titleLinksUpdate( $this->page );
511 - }
512 - }
513 - # Apply watchlist checkbox value (may be NULL)
514 - if ( $this->watchThis === true ) {
515 - $wgUser->addWatch( $this->page );
516 - } else if ( $this->watchThis === false ) {
517 - $wgUser->removeWatch( $this->page );
518 - }
519 - return true;
 320+ // If the this form is disabled, then return the "disabled" attr array
 321+ protected function disabledAttr() {
 322+ return $this->form->isAllowed()
 323+ ? array()
 324+ : array( 'disabled' => 'disabled' );
520325 }
521 -
522 - protected function updateConfigRow( $reset ) {
523 - $changed = false;
524 - $dbw = wfGetDB( DB_MASTER );
525 - # If setting to site default values and there is a row then erase it
526 - if ( $reset ) {
527 - $dbw->delete( 'flaggedpage_config',
528 - array( 'fpc_page_id' => $this->page->getArticleID() ),
529 - __METHOD__
530 - );
531 - $changed = ( $dbw->affectedRows() != 0 ); // did this do anything?
532 - # Otherwise, add/replace row if we are not just setting it to the site default
533 - } elseif ( !$reset ) {
534 - $dbExpiry = Block::encodeExpiry( $this->expiry, $dbw );
535 - $precedence = FlaggedRevs::useProtectionLevels()
536 - ? -1 // site default; fpc_select "don't care"
537 - : $this->select;
538 - # Get current config...
539 - $oldRow = $dbw->selectRow( 'flaggedpage_config',
540 - array( 'fpc_select', 'fpc_override', 'fpc_level', 'fpc_expiry' ),
541 - array( 'fpc_page_id' => $this->page->getArticleID() ),
542 - __METHOD__,
543 - 'FOR UPDATE'
544 - );
545 - # Check if this is not the same config as the existing row (if any)
546 - $changed = self::configIsDifferent( $oldRow,
547 - $precedence, $this->override, $this->autoreview, $dbExpiry );
548 - # If the new config is different, replace the old row...
549 - if ( $changed ) {
550 - $dbw->replace( 'flaggedpage_config',
551 - array( 'PRIMARY' ),
552 - array(
553 - 'fpc_page_id' => $this->page->getArticleID(),
554 - 'fpc_select' => intval( $precedence ),
555 - 'fpc_override' => intval( $this->override ),
556 - 'fpc_level' => $this->autoreview,
557 - 'fpc_expiry' => $dbExpiry
558 - ),
559 - __METHOD__
560 - );
561 - }
562 - }
563 - return $changed;
564 - }
565 -
566 - // Checks if new config is the same as the site default
567 - protected function configIsReset( $select, $override, $autoreview ) {
568 - # For protection config, just ignore the fpc_select column
569 - if( FlaggedRevs::useProtectionLevels() ) {
570 - return ( $autoreview == '' );
571 - } else {
572 - return ( $select == FlaggedRevs::getPrecedence()
573 - && $override == FlaggedRevs::isStableShownByDefault()
574 - && $autoreview == '' );
575 - }
576 - }
577 -
578 - // Checks if new config is different than the existing row
579 - protected function configIsDifferent( $oldRow, $select, $override, $autoreview, $dbExpiry ) {
580 - if( !$oldRow ) {
581 - return true; // no previous config
582 - }
583 - # For protection config, just ignore the fpc_select column
584 - if( FlaggedRevs::useProtectionLevels() ) {
585 - return ( $oldRow->fpc_override != $override // ...override changed, or...
586 - || $oldRow->fpc_level != $autoreview // ...autoreview level changed, or...
587 - || $oldRow->fpc_expiry != $dbExpiry // ...expiry changed
588 - );
589 - } else {
590 - return ( $oldRow->fpc_select != $select // ...precedence changed, or...
591 - || $oldRow->fpc_override != $override // ...override changed, or...
592 - || $oldRow->fpc_level != $autoreview // ...autoreview level changed, or...
593 - || $oldRow->fpc_expiry != $dbExpiry // ...expiry changed
594 - );
595 - }
596 - }
597326 }
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.hooks.php
@@ -1,4 +1,8 @@
22 <?php
 3+if ( !defined( 'MEDIAWIKI' ) ) {
 4+ echo "FlaggedRevs extension\n";
 5+ exit( 1 );
 6+}
37 /**
48 * Class containing hooked functions for a FlaggedRevs environment
59 */
@@ -2191,9 +2195,9 @@
21922196 # Close field set and table row
21932197 $output .= Xml::closeElement( 'fieldset' );
21942198 $output .= "</td></tr>";
2195 -
2196 - # Add some script for expiry dropdowns
2197 - Stabilization::addProtectionJS();
 2199+
 2200+ # Add some javascript for expiry dropdowns
 2201+ PageStabilityProtectForm::addProtectionJS();
21982202 return true;
21992203 }
22002204
@@ -2215,38 +2219,33 @@
22162220 global $wgUser, $wgRequest;
22172221 if ( !FlaggedRevs::useProtectionLevels() || !$article->exists() ) {
22182222 return true; // simple custom levels set for action=protect
2219 - }
2220 - if ( !FlaggedRevs::inReviewNamespace( $article->getTitle() ) ) {
 2223+ } elseif ( !FlaggedRevs::inReviewNamespace( $article->getTitle() ) ) {
22212224 return true; // not a reviewable page
2222 - }
2223 - if ( wfReadOnly() || !$wgUser->isAllowed( 'stablesettings' ) ) {
 2225+ } elseif ( wfReadOnly() || !$wgUser->isAllowed( 'stablesettings' ) ) {
22242226 return true; // user cannot change anything
22252227 }
2226 - $form = new Stabilization();
2227 - $form->target = $article->getTitle(); # Our target page
2228 - $form->watchThis = null; # protection form already has a watch check
2229 - $form->reason = $wgRequest->getText( 'mwProtect-reason' ); # Reason
2230 - $form->reasonSelection = $wgRequest->getVal( 'wpProtectReasonSelection' ); # Reason dropdown
2231 - $form->expiry = $wgRequest->getVal( 'mwStabilizeExpiryOther' ); # Expiry
2232 - $form->expirySelection = $wgRequest->getVal( 'mwStabilizeExpirySelection' ); # Expiry dropdown
 2228+ $form = new PageStabilityProtectForm();
 2229+ $form->setTarget( $article->getTitle() ); // target page
 2230+ $form->setWatchThis( null ); // protection form already has a watch check
 2231+ $form->setReason( $wgRequest->getText( 'mwProtect-reason' ) ); // manual
 2232+ $form->setReasonSelection( $wgRequest->getVal( 'wpProtectReasonSelection' ) ); // dropdown
 2233+ $form->setExpiry( $wgRequest->getVal( 'mwStabilizeExpiryOther' ) ); // manual
 2234+ $form->setExpirySelection( $wgRequest->getVal( 'mwStabilizeExpirySelection' ) ); // dropdown
22332235 # Fill in config from the protection level...
22342236 $permission = $wgRequest->getVal( 'mwStabilityConfig' );
22352237 if ( $permission == "none" ) {
2236 - $form->autoreview = ''; // default
2237 - } else if ( in_array( $permission, FlaggedRevs::getRestrictionLevels() ) ) {
2238 - $form->autoreview = $permission; // autoreview restriction
2239 - } else {
2240 - return false; // bad level, don't save!
 2238+ $permission = ''; // 'none' => ''
22412239 }
2242 - $form->reviewThis = null; // autoreview if not currently protected state
2243 - $form->override = null; // implied by autoreview level
2244 - $form->select = null; // site default
2245 - $form->wasPosted = $wgRequest->wasPosted();
2246 - if ( $form->handleParams() ) {
 2240+ $form->setAutoreview( $permission ); // autoreview restriction
 2241+ $form->setWasPosted( $wgRequest->wasPosted() ); // double-check
 2242+ $status = $form->handleParams();
 2243+ if ( $status === true ) {
22472244 $status = $form->submit();
22482245 if ( $status !== true ) {
22492246 $errorMsg = wfMsg( $status ); // some error message
22502247 }
 2248+ } else {
 2249+ $errorMsg = wfMsg( $status ); // some error message
22512250 }
22522251 return true;
22532252 }
Index: trunk/extensions/FlaggedRevs/api/ApiStabilize.php
@@ -31,86 +31,72 @@
3232 global $wgUser, $wgContLang;
3333 $params = $this->extractRequestParams();
3434
35 - if ( !isset( $params['title'] ) )
 35+ if ( !isset( $params['title'] ) ) {
3636 $this->dieUsageMsg( array( 'missingparam', 'title' ) );
37 - if ( !isset( $params['token'] ) )
 37+ } elseif ( !isset( $params['token'] ) ) {
3838 $this->dieUsageMsg( array( 'missingparam', 'token' ) );
 39+ }
3940
4041 $title = Title::newFromText( $params['title'] );
4142 if ( $title == null ) {
4243 $this->dieUsage( "Invalid title given.", "invalidtitle" );
4344 }
44 - if ( !FlaggedRevs::inReviewNamespace( $title ) ) {
45 - $this->dieUsage( "Title given does not correspond to a reviewable page.", "invalidtitle" );
46 - }
4745 $errors = $title->getUserPermissionsErrors( 'stablesettings', $wgUser );
4846 if ( $errors ) {
4947 // We don't care about multiple errors, just report one of them
5048 $this->dieUsageMsg( reset( $errors ) );
5149 }
52 -
53 - $article = new Article( $title );
54 - if ( !$article->exists() ) {
55 - $this->dieUsage( "Target page does not exist.", "invalidtitle" );
56 - }
 50+ // TODO: factory function?
 51+ $form = FlaggedRevs::useProtectionLevels()
 52+ ? new PageStabilityProtectForm()
 53+ : new PageStabilityForm();
5754
58 - $form = new Stabilization();
59 - $form->target = $title; # Our target page
60 - $form->watchThis = $params['watch']; # Watch this page
61 - $form->reviewThis = $params['review']; # Auto-review option
62 - $form->reason = $params['reason']; # Reason
63 - $form->reasonSelection = 'other'; # Reason dropdown
64 - $form->expiry = $params['expiry']; # Expiry
65 - $form->expirySelection = 'other'; # Expiry dropdown
66 -
67 - // Check if protection levels are enabled
 55+ $form->setTarget( $title ); # Our target page
 56+ $form->setWatchThis( $params['watch'] ); # Watch this page
 57+ $form->setReason( $params['reason'] ); # Reason
 58+ $form->setReasonSelection( 'other' ); # Reason dropdown
 59+ $form->setExpiry( $params['expiry'] ); # Expiry
 60+ $form->setExpirySelection( 'other' ); # Expiry dropdown
6861 if ( FlaggedRevs::useProtectionLevels() ) {
69 - $levels = FlaggedRevs::getRestrictionLevels();
70 - # Fill in config from the protection level...
71 - $selected = $params['protectlevel'];
72 - if ( $selected == "none" ) {
73 - $form->autoreview = ''; // default
74 - } else if ( in_array( $selected, $levels ) ) {
75 - $form->autoreview = $selected; // autoreview restriction
76 - } else {
77 - $this->dieUsage( "Invalid protection level given.", 'badprotectlevel' );
78 - }
79 - $form->override = null; // implied by autoreview level
80 - $form->select = null; // site default
 62+ $restriction = $params['protectlevel'];
8163 } else {
 64+ $restriction = $params['autoreview'];
8265 // Fill in config fields from URL params
83 - $form->select = $this->precendenceFromKey( $params['precedence'] );
 66+ $form->setPrecedence( $this->precendenceFromKey( $params['precedence'] ) );
8467 if ( $params['default'] === null ) {
 68+ // Default version setting not optional
8569 $this->dieUsageMsg( array( 'missingparam', 'default' ) );
8670 } else {
87 - $form->override = $this->defaultFromKey( $params['default'] );
 71+ $form->setOverride( $this->defaultFromKey( $params['default'] ) );
8872 }
89 - if ( $params['autoreview'] == 'none' ) {
90 - $form->autoreview = ''; // 'none' -> ''
91 - } else {
92 - $form->autoreview = $params['autoreview'];
93 - }
 73+ $form->setReviewThis( $params['review'] ); # Auto-review option
9474 }
95 - $form->wasPosted = true; // already validated
96 - if ( $form->handleParams() ) {
 75+ if ( $restriction == 'none' ) {
 76+ $restriction = ''; // 'none' => ''
 77+ }
 78+ $form->setAutoreview( $restriction ); # Autoreview restriction
 79+ $form->setWasPosted( true ); // already validated
 80+
 81+ $status = $form->handleParams();
 82+ if ( $status === true ) {
9783 $status = $form->submit(); // true/error message key
9884 if ( $status !== true ) {
9985 $this->dieUsage( wfMsg( $status ) );
10086 }
10187 } else {
102 - $this->dieUsage( "Invalid config parameters given. The precendence level may beyond your rights.", 'invalidconfig' );
 88+ $this->dieUsage( wfMsg( $status ), $status );
10389 }
10490 # Output success line with the title and config parameters
10591 $res = array();
10692 $res['title'] = $title->getPrefixedText();
107 - if ( count( $levels ) ) {
 93+ if ( FlaggedRevs::useProtectionLevels() ) {
10894 $res['protectlevel'] = $params['protectlevel'];
10995 } else {
11096 $res['default'] = $params['default'];
11197 $res['precedence'] = $params['precedence'];
11298 $res['autoreview'] = $params['autoreview'];
11399 }
114 - $res['expiry'] = $form->expiry;
 100+ $res['expiry'] = $form->getExpiry();
115101 $this->getResult()->addValue( null, $this->getModuleName(), $res );
116102 }
117103

Status & tagging log