Index: trunk/phase3/docs/hooks.txt |
— | — | @@ -1209,6 +1209,18 @@ |
1210 | 1210 | $newPass: new password |
1211 | 1211 | $error: error (string) 'badretype', 'wrongpassword', 'error' or 'success' |
1212 | 1212 | |
| 1213 | +'ProtectionForm::buildForm': called after all protection type fieldsets are made in the form |
| 1214 | +$article: the title being (un)protected |
| 1215 | +$output: a string of the form HTML so far |
| 1216 | + |
| 1217 | +'ProtectionForm::showLogExtract': called after the protection log extract is shown |
| 1218 | +$article: the page the form is shown for |
| 1219 | +$out: OutputPage object |
| 1220 | + |
| 1221 | +'ProtectionForm::save': called when a protection form is submitted |
| 1222 | +$article: the title being (un)protected |
| 1223 | +$errorMsg: an html message string of an error |
| 1224 | + |
1213 | 1225 | 'RawPageViewBeforeOutput': Right before the text is blown out in action=raw |
1214 | 1226 | &$obj: RawPage object |
1215 | 1227 | &$text: The text that's going to be the output |
Index: trunk/phase3/includes/ProtectionForm.php |
— | — | @@ -274,6 +274,16 @@ |
275 | 275 | throw new FatalError( "Unknown error at restriction save time." ); |
276 | 276 | } |
277 | 277 | |
| 278 | + $errorMsg = ''; |
| 279 | + # Give extensions a change to handle added form items |
| 280 | + if( !wfRunHooks( 'ProtectionForm::save', array($this->mArticle,&$errorMsg) ) ) { |
| 281 | + throw new FatalError( "Unknown hook error at restriction save time." ); |
| 282 | + } |
| 283 | + if( $errorMsg != '' ) { |
| 284 | + $this->show( $errorMsg ); |
| 285 | + return false; |
| 286 | + } |
| 287 | + |
278 | 288 | if( $wgRequest->getCheck( 'mwProtectWatch' ) ) { |
279 | 289 | $this->mArticle->doWatch(); |
280 | 290 | } elseif( $this->mTitle->userIsWatching() ) { |
— | — | @@ -390,6 +400,8 @@ |
391 | 401 | Xml::closeElement( 'fieldset' ) . |
392 | 402 | "</td></tr>"; |
393 | 403 | } |
| 404 | + # Give extensions a chance to add items to the form |
| 405 | + wfRunHooks( 'ProtectionForm::buildForm', array($this->mArticle,&$out) ); |
394 | 406 | |
395 | 407 | $out .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' ); |
396 | 408 | |
— | — | @@ -554,5 +566,7 @@ |
555 | 567 | # Show relevant lines from the protection log: |
556 | 568 | $out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'protect' ) ) ); |
557 | 569 | LogEventsList::showLogExtract( $out, 'protect', $this->mTitle->getPrefixedText() ); |
| 570 | + # Let extensions add other relevant log extracts |
| 571 | + wfRunHooks( 'ProtectionForm::showLogExtract', array($this->mArticle,$out) ); |
558 | 572 | } |
559 | 573 | } |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.php |
— | — | @@ -143,6 +143,15 @@ |
144 | 144 | # 0 => sighted; 1 => quality; 2 => pristine |
145 | 145 | $wgFlaggedRevsPatrolLevel = 0; |
146 | 146 | |
| 147 | +# Stability levels, defined below, that appear in protection form |
| 148 | +$wgFlaggedRevsProtectLevels = array(); |
| 149 | +/* (example usage) |
| 150 | +$wgFlaggedRevsProtectLevels = array( |
| 151 | + 'semi-review' => array('select' => FLAGGED_VIS_LATEST, 'override' => true, 'autoreview' => ''), |
| 152 | + 'intm-review' => array('select' => FLAGGED_VIS_LATEST, 'override' => true, 'autoreview' => 'review'), |
| 153 | +); |
| 154 | +*/ |
| 155 | + |
147 | 156 | # Restriction levels for auto-review right at Stabilization page |
148 | 157 | $wgFlaggedRevsRestrictionLevels = array( '', 'sysop' ); |
149 | 158 | |
— | — | @@ -417,6 +426,10 @@ |
418 | 427 | $wgHooks['EditPage::showEditForm:initial'][] = 'FlaggedRevsHooks::addToEditView'; |
419 | 428 | # Add review form and visiblity settings link |
420 | 429 | $wgHooks['SkinAfterContent'][] = 'FlaggedRevsHooks::onSkinAfterContent'; |
| 430 | +# Add protection form field |
| 431 | +$wgHooks['ProtectionForm::buildForm'][] = 'FlaggedRevsHooks::onProtectionForm'; |
| 432 | +$wgHooks['ProtectionForm::showLogExtract'][] = 'FlaggedRevsHooks::insertStabilityLog'; |
| 433 | +$wgHooks['ProtectionForm::save'][] = 'FlaggedRevsHooks::onProtectionSave'; |
421 | 434 | # Mark items in page history |
422 | 435 | $wgHooks['PageHistoryPager::getQueryInfo'][] = 'FlaggedRevsHooks::addToHistQuery'; |
423 | 436 | $wgHooks['PageHistoryLineEnding'][] = 'FlaggedRevsHooks::addToHistLine'; |
— | — | @@ -496,11 +509,12 @@ |
497 | 510 | * Also sets $wgSpecialPages just to be consistent. |
498 | 511 | */ |
499 | 512 | function efLoadFlaggedRevsSpecialPages( &$list ) { |
500 | | - global $wgSpecialPages, $wgFlaggedRevsNamespaces, $wgFlaggedRevsOverride; |
| 513 | + global $wgSpecialPages, $wgFlaggedRevsNamespaces, $wgFlaggedRevsOverride, $wgFlaggedRevsProtectLevels; |
501 | 514 | if( !empty($wgFlaggedRevsNamespaces) ) { |
502 | 515 | $list['RevisionReview'] = $wgSpecialPages['RevisionReview'] = 'RevisionReview'; |
503 | 516 | $list['StableVersions'] = $wgSpecialPages['StableVersions'] = 'StableVersions'; |
504 | | - $list['Stabilization'] = $wgSpecialPages['Stabilization'] = 'Stabilization'; |
| 517 | + if( empty($wgFlaggedRevsProtectLevels) ) |
| 518 | + $list['Stabilization'] = $wgSpecialPages['Stabilization'] = 'Stabilization'; |
505 | 519 | $list['UnreviewedPages'] = $wgSpecialPages['UnreviewedPages'] = 'UnreviewedPages'; |
506 | 520 | $list['OldReviewedPages'] = $wgSpecialPages['OldReviewedPages'] = 'OldReviewedPages'; |
507 | 521 | $list['ProblemChanges'] = $wgSpecialPages['ProblemChanges'] = 'ProblemChanges'; |
Index: trunk/extensions/FlaggedRevs/FlaggedArticle.php |
— | — | @@ -897,6 +897,8 @@ |
898 | 898 | */ |
899 | 899 | public function addVisibilityLink( &$data ) { |
900 | 900 | global $wgUser, $wgRequest, $wgOut; |
| 901 | + if( FlaggedRevs::getProtectionLevels() ) |
| 902 | + return true; // simple custom levels set for action=protect |
901 | 903 | # Check only if the title is reviewable |
902 | 904 | if( !$this->isReviewable(true) ) { |
903 | 905 | return true; |
— | — | @@ -931,7 +933,9 @@ |
932 | 934 | */ |
933 | 935 | public function setActionTabs( $skin, &$actions ) { |
934 | 936 | global $wgRequest, $wgUser; |
935 | | - |
| 937 | + if( FlaggedRevs::getProtectionLevels() ) { |
| 938 | + return true; // simple custom levels set for action=protect |
| 939 | + } |
936 | 940 | $title = $this->parent->getTitle()->getSubjectPage(); |
937 | 941 | if ( !FlaggedRevs::isPageReviewable( $title ) ) { |
938 | 942 | return true; // Only reviewable pages need these tabs |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.class.php |
— | — | @@ -56,6 +56,13 @@ |
57 | 57 | self::$minPL[$tag] = max($minPL,1); |
58 | 58 | self::$minSL[$tag] = 1; |
59 | 59 | } |
| 60 | + global $wgFlaggedRevsProtectLevels; |
| 61 | + foreach( $wgFlaggedRevsProtectLevels as $level => $config ) { |
| 62 | + # Sanity checks |
| 63 | + if( !isset($config['select']) || !isset($config['override']) || !isset($config['autoreview']) ) { |
| 64 | + throw new MWException( 'FlaggedRevs given incomplete $wgFlaggedRevsProtectLevels value!' ); |
| 65 | + } |
| 66 | + } |
60 | 67 | self::$loaded = true; |
61 | 68 | } |
62 | 69 | |
— | — | @@ -142,7 +149,17 @@ |
143 | 150 | self::load(); |
144 | 151 | return $wgFlaggedRevsLowProfile; |
145 | 152 | } |
| 153 | + |
146 | 154 | /** |
| 155 | + * Get the site defined protection levels for review |
| 156 | + * @returns array |
| 157 | + */ |
| 158 | + public static function getProtectionLevels() { |
| 159 | + global $wgFlaggedRevsProtectLevels; |
| 160 | + return $wgFlaggedRevsProtectLevels; |
| 161 | + } |
| 162 | + |
| 163 | + /** |
147 | 164 | * Should comments be allowed on pages and forms? |
148 | 165 | * @returns bool |
149 | 166 | */ |
— | — | @@ -996,7 +1013,7 @@ |
997 | 1014 | * @param bool $forUpdate, use master DB? |
998 | 1015 | * @returns Array (select,override) |
999 | 1016 | */ |
1000 | | - public static function getPageVisibilitySettings( &$title, $forUpdate=false ) { |
| 1017 | + public static function getPageVisibilitySettings( $title, $forUpdate=false ) { |
1001 | 1018 | $db = $forUpdate ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE ); |
1002 | 1019 | $row = $db->selectRow( 'flaggedpage_config', |
1003 | 1020 | array( 'fpc_select', 'fpc_override', 'fpc_level', 'fpc_expiry' ), |
Index: trunk/extensions/FlaggedRevs/language/FlaggedRevs.i18n.php |
— | — | @@ -206,6 +206,9 @@ |
207 | 207 | 'tooltip-ca-current' => 'View the current draft of this page', |
208 | 208 | 'tooltip-ca-stable' => 'View the stable version of this page', |
209 | 209 | 'tooltip-ca-default' => 'Quality assurance settings', |
| 210 | + |
| 211 | + 'flaggedrevs-protect-legend' => 'Edit approval', |
| 212 | + 'flaggedrevs-protect-none' => 'No additional restrictions', |
210 | 213 | |
211 | 214 | 'revreview-locked-title' => 'Edits must be reviewed before being displayed on this page.', |
212 | 215 | 'revreview-unlocked-title' => 'Edits do not require review before being displayed on this page.', |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.hooks.php |
— | — | @@ -1805,6 +1805,173 @@ |
1806 | 1806 | $join['revision'] = array('INNER JOIN','rev_page = fp_page_id AND rev_id = fp_stable'); |
1807 | 1807 | return false; // final |
1808 | 1808 | } |
| 1809 | + |
| 1810 | + // Add radio of review "protection" options |
| 1811 | + // Code stolen from Stabilization (which was stolen from ProtectionForm) |
| 1812 | + public static function onProtectionForm( $article, &$output ) { |
| 1813 | + global $wgUser, $wgRequest, $wgOut, $wgLang; |
| 1814 | + if( !count( FlaggedRevs::getProtectionLevels() ) ) |
| 1815 | + return true; // nothing to do |
| 1816 | + # Can the user actually do anything? |
| 1817 | + $isAllowed = $wgUser->isAllowed('stablesettings'); |
| 1818 | + $disabledAttrib = !$isAllowed ? array( 'disabled' => 'disabled' ) : array(); |
| 1819 | + # Load request params... |
| 1820 | + $selected = $wgRequest->getVal( 'wpStabilityConfig' ); |
| 1821 | + $expiry = $wgRequest->getText( 'mwStabilize-expiry' ); |
| 1822 | + $reviewThis = $wgRequest->getBool( 'wpReviewthis', true ); |
| 1823 | + # Get the current config/expiry |
| 1824 | + $config = FlaggedRevs::getPageVisibilitySettings( $article->getTitle(), true ); |
| 1825 | + $oldExpiry = $config['expiry'] !== 'infinity' ? |
| 1826 | + wfTimestamp( TS_RFC2822, $config['expiry'] ) : 'infinite'; |
| 1827 | + # Add some script for expiry dropdowns |
| 1828 | + $wgOut->addScript( |
| 1829 | + "<script type=\"text/javascript\"> |
| 1830 | + function updateStabilizationDropdowns() { |
| 1831 | + val = document.getElementById('mwExpirySelection').value; |
| 1832 | + if( val == 'existing' ) |
| 1833 | + document.getElementById('mwStabilize-expiry').value = ". |
| 1834 | + Xml::encodeJsVar($oldExpiry)."; |
| 1835 | + else if( val != 'othertime' ) |
| 1836 | + document.getElementById('mwStabilize-expiry').value = val; |
| 1837 | + } |
| 1838 | + </script>" |
| 1839 | + ); |
| 1840 | + # Add an extra row to the protection fieldset tables |
| 1841 | + $output .= "<tr><td>"; |
| 1842 | + $output .= Xml::openElement( 'fieldset' ); |
| 1843 | + $output .= Xml::element( 'legend', null, wfMsg('flaggedrevs-protect-legend') ); |
| 1844 | + $output .= "<table>"; |
| 1845 | + # Add a "no restrictions" level |
| 1846 | + $effectiveLevels = array( "none" => null ); |
| 1847 | + $effectiveLevels += FlaggedRevs::getProtectionLevels(); |
| 1848 | + # Show all restriction levels as radios... |
| 1849 | + foreach( $effectiveLevels as $level => $x ) { |
| 1850 | + $label = wfMsg( 'flaggedrevs-protect-'.$level ); |
| 1851 | + // Default to the key itself if no UI message |
| 1852 | + if( wfEmptyMsg('flaggedrevs-protect-'.$level,$label) ) { |
| 1853 | + $label = 'flaggedrevs-protect-'.$level; |
| 1854 | + } |
| 1855 | + $output .= "<tr><td>" . Xml::radioLabel( $label, 'wpStabilityConfig', $level, |
| 1856 | + 'wpStabilityConfig-'.$level, $level == $selected, $disabledAttrib ) . "</td></tr>"; |
| 1857 | + } |
| 1858 | + $output .= "</table>"; |
| 1859 | + # Get expiry dropdown |
| 1860 | + $scExpiryOptions = wfMsgForContent( 'protect-expiry-options' ); |
| 1861 | + $showProtectOptions = ($scExpiryOptions !== '-' && $isAllowed); |
| 1862 | + # Add the current expiry as an option |
| 1863 | + $expiryFormOptions = ''; |
| 1864 | + if( $config['expiry'] && $config['expiry'] != 'infinity' ) { |
| 1865 | + $timestamp = $wgLang->timeanddate( $config['expiry'] ); |
| 1866 | + $d = $wgLang->date( $config['expiry'] ); |
| 1867 | + $t = $wgLang->time( $config['expiry'] ); |
| 1868 | + $expiryFormOptions .= |
| 1869 | + Xml::option( |
| 1870 | + wfMsg( 'protect-existing-expiry', $timestamp, $d, $t ), |
| 1871 | + 'existing', |
| 1872 | + $config['expiry'] == 'existing' |
| 1873 | + ) . "\n"; |
| 1874 | + } |
| 1875 | + $expiryFormOptions .= Xml::option( wfMsg( 'protect-othertime-op' ), "othertime" ) . "\n"; |
| 1876 | + # Add custom levels (from MediaWiki message) |
| 1877 | + foreach( explode(',',$scExpiryOptions) as $option ) { |
| 1878 | + if( strpos($option,":") === false ) { |
| 1879 | + $show = $value = $option; |
| 1880 | + } else { |
| 1881 | + list($show, $value) = explode(":",$option); |
| 1882 | + } |
| 1883 | + $show = htmlspecialchars($show); |
| 1884 | + $value = htmlspecialchars($value); |
| 1885 | + $expiryFormOptions .= Xml::option( $show, $value, $config['expiry'] === $value ) . "\n"; |
| 1886 | + } |
| 1887 | + # Add expiry dropdown to form |
| 1888 | + $scExpiryOptions = wfMsgForContent( 'protect-expiry-options' ); |
| 1889 | + $showProtectOptions = ($scExpiryOptions !== '-' && $isAllowed); |
| 1890 | + $output .= "<table>"; // expiry table start |
| 1891 | + if( $showProtectOptions && $isAllowed ) { |
| 1892 | + $output .= " |
| 1893 | + <tr> |
| 1894 | + <td class='mw-label'>" . |
| 1895 | + Xml::label( wfMsg('stabilization-expiry'), 'mwExpirySelection' ) . |
| 1896 | + "</td> |
| 1897 | + <td class='mw-input'>" . |
| 1898 | + Xml::tags( 'select', |
| 1899 | + array( |
| 1900 | + 'id' => 'mwExpirySelection', |
| 1901 | + 'name' => 'wpExpirySelection', |
| 1902 | + 'onchange' => 'updateStabilizationDropdowns()', |
| 1903 | + ) + $disabledAttrib, |
| 1904 | + $expiryFormOptions ) . |
| 1905 | + "</td> |
| 1906 | + </tr>"; |
| 1907 | + } |
| 1908 | + # Add custom expiry field to form |
| 1909 | + $attribs = array( 'id' => "mwStabilize-expiry", |
| 1910 | + 'onkeyup' => 'updateStabilizationDropdowns()' ) + $disabledAttrib; |
| 1911 | + $output .= " |
| 1912 | + <tr> |
| 1913 | + <td class='mw-label'>" . |
| 1914 | + Xml::label( wfMsg('stabilization-othertime'), 'mwStabilize-expiry' ) . |
| 1915 | + '</td> |
| 1916 | + <td class="mw-input">' . |
| 1917 | + Xml::input( "mwStabilize-expiry", 50, |
| 1918 | + $expiry ? $expiry : $oldExpiry, $attribs ) . |
| 1919 | + '</td> |
| 1920 | + </tr>'; |
| 1921 | + $output .= "</table>"; // expiry table end |
| 1922 | + # Add "review this page" checkbox |
| 1923 | + $reviewLabel = wfMsgExt( 'stabilization-review', array('parseinline') ); |
| 1924 | + $output .= Xml::checkLabel( $reviewLabel, 'wpReviewthis', $reviewThis, array('id'=>'wpReviewthis') ); |
| 1925 | + # Close field set and table row |
| 1926 | + $output .= Xml::closeElement( 'fieldset' ); |
| 1927 | + $output .= "</td></tr>"; |
| 1928 | + return true; |
| 1929 | + } |
| 1930 | + |
| 1931 | + // Add stability log extract to protection form |
| 1932 | + public static function insertStabilityLog( $article, $out ) { |
| 1933 | + # Show relevant lines from the stability log: |
| 1934 | + $out->addHTML( Xml::element( 'h2', null, LogPage::logName('stable') ) ); |
| 1935 | + LogEventsList::showLogExtract( $out, 'stable', $article->getTitle()->getPrefixedText() ); |
| 1936 | + return true; |
| 1937 | + } |
| 1938 | + |
| 1939 | + // Update stability config from request |
| 1940 | + public static function onProtectionSave( $article, &$errorMsg ) { |
| 1941 | + global $wgUser, $wgRequest; |
| 1942 | + if( wfReadOnly() || !$wgUser->isAllowed('stablesettings') ) { |
| 1943 | + return true; // user cannot change anything |
| 1944 | + } |
| 1945 | + $form = new Stabilization(); |
| 1946 | + $form->target = $article->getTitle(); # Our target page |
| 1947 | + $form->watchThis = null; // protection form already has a watch check |
| 1948 | + $form->reviewThis = $wgRequest->getBool( 'wpReviewthis', true ); # Auto-review option |
| 1949 | + $form->reason = $wgRequest->getVal( 'wpReason' ); # Reason |
| 1950 | + $form->reasonSelection = $wgRequest->getText( 'wpReasonSelection' ); # Reason dropdown |
| 1951 | + $form->expiry = $wgRequest->getText( 'mwStabilize-expiry' ); # Expiry |
| 1952 | + $form->expirySelection = $wgRequest->getVal( 'wpExpirySelection' ); # Expiry dropdown |
| 1953 | + # Fill in config from the protection level... |
| 1954 | + $selected = $wgRequest->getVal( 'wpStabilityConfig' ); |
| 1955 | + $levels = FlaggedRevs::getProtectionLevels(); |
| 1956 | + if( $selected == "none" ) { |
| 1957 | + $form->select = FlaggedRevs::getPrecedence(); // default |
| 1958 | + $form->override = FlaggedRevs::showStableByDefault(); // default |
| 1959 | + $form->autoreview = ''; // default |
| 1960 | + } else if( isset($levels[$selected]) ) { |
| 1961 | + $form->select = $levels[$selected]['select']; |
| 1962 | + $form->override = $levels[$selected]['override']; |
| 1963 | + $form->autoreview = $levels[$selected]['autoreview']; |
| 1964 | + } else { |
| 1965 | + return false; // bad level |
| 1966 | + } |
| 1967 | + $form->wasPosted = $wgRequest->wasPosted(); |
| 1968 | + if( $form->handleParams() ) { |
| 1969 | + $status = $form->submit(); |
| 1970 | + if( $status !== true ) { |
| 1971 | + $errorMsg = wfMsg($status); // some error message |
| 1972 | + } |
| 1973 | + } |
| 1974 | + return true; |
| 1975 | + } |
1809 | 1976 | |
1810 | 1977 | public static function onParserTestTables( &$tables ) { |
1811 | 1978 | $tables[] = 'flaggedpages'; |