Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -1143,6 +1143,7 @@ |
1144 | 1144 | 'rightslogtext', |
1145 | 1145 | 'rightslogentry', |
1146 | 1146 | 'rightsnone', |
| 1147 | + 'rightsautocomment', |
1147 | 1148 | ), |
1148 | 1149 | 'action' => array( |
1149 | 1150 | 'action-read', |
Index: trunk/phase3/includes/Defines.php |
— | — | @@ -249,4 +249,5 @@ |
250 | 250 | define( 'APCOND_IPINRANGE', 6 ); |
251 | 251 | define( 'APCOND_AGE_FROM_EDIT', 7 ); |
252 | 252 | define( 'APCOND_BLOCKED', 8 ); |
| 253 | +define( 'APCOND_ISBOT', 9 ); |
253 | 254 | /**@}*/ |
Index: trunk/phase3/includes/User.php |
— | — | @@ -1117,14 +1117,25 @@ |
1118 | 1118 | * @see $wgAutopromoteOnce |
1119 | 1119 | */ |
1120 | 1120 | public function addAutopromoteOnceGroups( $event ) { |
| 1121 | + $toPromote = array(); |
1121 | 1122 | if ( $this->getId() ) { |
1122 | 1123 | $toPromote = Autopromote::getAutopromoteOnceGroups( $this, $event ); |
1123 | | - foreach ( $toPromote as $group ) { |
1124 | | - $this->addGroup( $group ); |
| 1124 | + if ( count( $toPromote ) ) { |
| 1125 | + $oldGroups = $this->getGroups(); // previous groups |
| 1126 | + foreach ( $toPromote as $group ) { |
| 1127 | + $this->addGroup( $group ); |
| 1128 | + } |
| 1129 | + $newGroups = array_merge( $oldGroups, $toPromote ); // all groups |
| 1130 | + |
| 1131 | + $log = new LogPage( 'rights', false /* not in RC */ ); |
| 1132 | + $log->addEntry( 'rights', |
| 1133 | + $this->getUserPage(), |
| 1134 | + wfMsgForContent( 'rightsautocomment' ), |
| 1135 | + array( implode( ', ', $oldGroups ), implode( ', ', $newGroups ) ) |
| 1136 | + ); |
1125 | 1137 | } |
1126 | | - return $toPromote; |
1127 | 1138 | } |
1128 | | - return array(); |
| 1139 | + return $toPromote; |
1129 | 1140 | } |
1130 | 1141 | |
1131 | 1142 | /** |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -3498,7 +3498,7 @@ |
3499 | 3499 | /** |
3500 | 3500 | * Automatically add a usergroup to any user who matches certain conditions. |
3501 | 3501 | * The format is |
3502 | | - * array( '&' or '|' or '^', cond1, cond2, ... ) |
| 3502 | + * array( '&' or '|' or '^' or '!', cond1, cond2, ... ) |
3503 | 3503 | * where cond1, cond2, ... are themselves conditions; *OR* |
3504 | 3504 | * APCOND_EMAILCONFIRMED, *OR* |
3505 | 3505 | * array( APCOND_EMAILCONFIRMED ), *OR* |
— | — | @@ -3509,6 +3509,7 @@ |
3510 | 3510 | * array( APCOND_IPINRANGE, range ), *OR* |
3511 | 3511 | * array( APCOND_AGE_FROM_EDIT, seconds since first edit ), *OR* |
3512 | 3512 | * array( APCOND_BLOCKED ), *OR* |
| 3513 | + * array( APCOND_ISBOT ), *OR* |
3513 | 3514 | * similar constructs defined by extensions. |
3514 | 3515 | * |
3515 | 3516 | * If $wgEmailAuthentication is off, APCOND_EMAILCONFIRMED will be true for any |
Index: trunk/phase3/includes/Autopromote.php |
— | — | @@ -68,7 +68,7 @@ |
69 | 69 | |
70 | 70 | /** |
71 | 71 | * Recursively check a condition. Conditions are in the form |
72 | | - * array( '&' or '|' or '^', cond1, cond2, ... ) |
| 72 | + * array( '&' or '|' or '^' or '!', cond1, cond2, ... ) |
73 | 73 | * where cond1, cond2, ... are themselves conditions; *OR* |
74 | 74 | * APCOND_EMAILCONFIRMED, *OR* |
75 | 75 | * array( APCOND_EMAILCONFIRMED ), *OR* |
— | — | @@ -176,6 +176,8 @@ |
177 | 177 | return IP::isInRange( wfGetIP(), $cond[1] ); |
178 | 178 | case APCOND_BLOCKED: |
179 | 179 | return $user->isBlocked(); |
| 180 | + case APCOND_ISBOT: |
| 181 | + return in_array( 'bot', User::getGroupPermissions( $user->getGroups() ) ); |
180 | 182 | default: |
181 | 183 | $result = null; |
182 | 184 | wfRunHooks( 'AutopromoteCondition', array( $cond[0], array_slice( $cond, 1 ), $user, &$result ) ); |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -1978,10 +1978,11 @@ |
1979 | 1979 | 'right-sendemail' => 'Send e-mail to other users', |
1980 | 1980 | |
1981 | 1981 | # User rights log |
1982 | | -'rightslog' => 'User rights log', |
1983 | | -'rightslogtext' => 'This is a log of changes to user rights.', |
1984 | | -'rightslogentry' => 'changed group membership for $1 from $2 to $3', |
1985 | | -'rightsnone' => '(none)', |
| 1982 | +'rightslog' => 'User rights log', |
| 1983 | +'rightslogtext' => 'This is a log of changes to user rights.', |
| 1984 | +'rightslogentry' => 'changed group membership for $1 from $2 to $3', |
| 1985 | +'rightsnone' => '(none)', |
| 1986 | +'rightsautocomment' => 'automatically promoted', |
1986 | 1987 | |
1987 | 1988 | # Associated actions - in the sentence "You do not have permission to X" |
1988 | 1989 | 'action-read' => 'read this page', |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.php |
— | — | @@ -473,8 +473,6 @@ |
474 | 474 | $wgHooks['NewRevisionFromEditComplete'][] = 'FlaggedRevsHooks::maybeMakeEditReviewed'; |
475 | 475 | # Null edit review via checkbox |
476 | 476 | $wgHooks['ArticleSaveComplete'][] = 'FlaggedRevsHooks::maybeNullEditReview'; |
477 | | -# Disable auto-promotion for demoted users |
478 | | -$wgHooks['UserRights'][] = 'FlaggedRevsHooks::recordDemote'; |
479 | 477 | # User edit tallies |
480 | 478 | $wgHooks['ArticleRollbackComplete'][] = 'FlaggedRevsHooks::incrementRollbacks'; |
481 | 479 | $wgHooks['NewRevisionFromEditComplete'][] = 'FlaggedRevsHooks::incrementReverts'; |
— | — | @@ -525,13 +523,12 @@ |
526 | 524 | # ######## |
527 | 525 | |
528 | 526 | function efSetFlaggedRevsConditionalHooks() { |
529 | | - global $wgHooks; |
| 527 | + global $wgHooks, $wgFlaggedRevsProtection; |
530 | 528 | # Mark items in user contribs |
531 | | - if ( !FlaggedRevs::useOnlyIfProtected() ) { |
| 529 | + if ( !$wgFlaggedRevsProtection ) { |
532 | 530 | $wgHooks['ContribsPager::getQueryInfo'][] = 'FlaggedRevsUIHooks::addToContribsQuery'; |
533 | 531 | $wgHooks['ContributionsLineEnding'][] = 'FlaggedRevsUIHooks::addToContribsLine'; |
534 | | - } |
535 | | - if ( FlaggedRevs::useProtectionLevels() ) { |
| 532 | + } else { |
536 | 533 | # Add protection form field |
537 | 534 | $wgHooks['ProtectionForm::buildForm'][] = 'FlaggedRevsUIHooks::onProtectionForm'; |
538 | 535 | $wgHooks['ProtectionForm::showLogExtract'][] = 'FlaggedRevsUIHooks::insertStabilityLog'; |
— | — | @@ -550,8 +547,10 @@ |
551 | 548 | |
552 | 549 | # ####### END HOOK TRIGGERED FUNCTIONS ######### |
553 | 550 | |
| 551 | +// Note: avoid calls to FlaggedRevs class here for performance |
554 | 552 | function efLoadFlaggedRevs() { |
555 | | - global $wgFlaggedRevsRCCrap, $wgUseRCPatrol, $wgFlaggedRevsNamespaces; |
| 553 | + global $wgFlaggedRevsRCCrap, $wgUseRCPatrol; |
| 554 | + global $wgFlaggedRevsNamespaces, $wgFlaggedRevsProtection; |
556 | 555 | if ( $wgFlaggedRevsRCCrap ) { |
557 | 556 | # If patrolling is already on, then we know that it |
558 | 557 | # was intended to have all namespaces patrollable. |
— | — | @@ -561,13 +560,29 @@ |
562 | 561 | } |
563 | 562 | /* TODO: decouple from rc patrol */ |
564 | 563 | # Check if FlaggedRevs is enabled by default for pages... |
565 | | - if ( $wgFlaggedRevsNamespaces && !FlaggedRevs::useOnlyIfProtected() ) { |
| 564 | + if ( $wgFlaggedRevsNamespaces && !$wgFlaggedRevsProtection ) { |
566 | 565 | # Use RC Patrolling to check for vandalism. |
567 | 566 | # Edits to reviewable pages must be flagged to be patrolled. |
568 | 567 | $wgUseRCPatrol = true; |
569 | 568 | } |
570 | 569 | } |
571 | | - global $wgFlaggedRevsAutoconfirm, $wgAutopromoteOnce; |
| 570 | + |
| 571 | + # Conditional autopromote groups |
| 572 | + efSetFlaggedRevsAutopromoteConfig(); |
| 573 | + |
| 574 | + # Conditional API modules |
| 575 | + efSetFlaggedRevsConditionalAPIModules(); |
| 576 | + # Load hooks that aren't always set |
| 577 | + efSetFlaggedRevsConditionalHooks(); |
| 578 | + # Remove conditionally applicable rights |
| 579 | + efSetFlaggedRevsConditionalRights(); |
| 580 | + # Defaults for user preferences |
| 581 | + efSetFlaggedRevsConditionalPreferences(); |
| 582 | +} |
| 583 | + |
| 584 | +function efSetFlaggedRevsAutopromoteConfig() { |
| 585 | + global $wgFlaggedRevsAutoconfirm, $wgFlaggedRevsAutopromote; |
| 586 | + global $wgAutopromoteOnce, $wgGroupPermissions; |
572 | 587 | # $wgFlaggedRevsAutoconfirm is now a wrapper around $wgAutopromoteOnce |
573 | 588 | $req = $wgFlaggedRevsAutoconfirm; // convenience |
574 | 589 | if ( is_array( $req ) ) { |
— | — | @@ -589,20 +604,39 @@ |
590 | 605 | $criteria[] = array( APCOND_FR_NEVERBOCKED ); |
591 | 606 | } |
592 | 607 | $wgAutopromoteOnce['onEdit']['autoreview'] = $criteria; |
| 608 | + $wgGroupPermissions['autoreview']['autoreview'] = true; |
593 | 609 | } |
594 | | - # Conditional API modules |
595 | | - efSetFlaggedRevsConditionalAPIModules(); |
596 | | - # Load hooks that aren't always set |
597 | | - efSetFlaggedRevsConditionalHooks(); |
598 | | - # Remove conditionally applicable rights |
599 | | - efSetFlaggedRevsConditionalRights(); |
600 | | - # Defaults for user preferences |
601 | | - efSetFlaggedRevsConditionalPreferences(); |
| 610 | + |
| 611 | + # $wgFlaggedRevsAutoconfirm is now a wrapper around $wgAutopromoteOnce |
| 612 | + $req = $wgFlaggedRevsAutopromote; // convenience |
| 613 | + if ( is_array( $req ) ) { |
| 614 | + $criteria = array( '&', // AND |
| 615 | + array( APCOND_AGE, $req['days']*86400 ), |
| 616 | + array( APCOND_FR_EDITCOUNT, $req['edits'], $req['excludeLastDays']*86400 ), |
| 617 | + array( APCOND_FR_EDITSUMMARYCOUNT, $req['editComments'] ), |
| 618 | + array( APCOND_FR_UNIQUEPAGECOUNT, $req['uniqueContentPages'] ), |
| 619 | + array( APCOND_FR_USERPAGEBYTES, $req['userpageBytes'] ), |
| 620 | + array( APCOND_FR_NEVERDEMOTED ), // for b/c |
| 621 | + array( APCOND_FR_EDITSPACING, $req['spacing'], $req['benchmarks'] ), |
| 622 | + array( '|', // OR |
| 623 | + array( APCOND_FR_CONTENTEDITCOUNT, |
| 624 | + $req['totalContentEdits'], $req['excludeLastDays']*86400 ), |
| 625 | + array( APCOND_FR_CHECKEDEDITCOUNT, |
| 626 | + $req['totalCheckedEdits'], $req['excludeLastDays']*86400 ) |
| 627 | + ), |
| 628 | + array( APCOND_FR_MAXREVERTEDEDITRATIO, $req['maxRevertedEditRatio'] ), |
| 629 | + array( '!', APCOND_ISBOT ) |
| 630 | + ); |
| 631 | + if ( $req['neverBlocked'] ) { |
| 632 | + $criteria[] = array( APCOND_FR_NEVERBOCKED ); |
| 633 | + } |
| 634 | + $wgAutopromoteOnce['onEdit']['editor'] = $criteria; |
| 635 | + } |
602 | 636 | } |
603 | 637 | |
604 | 638 | function efSetFlaggedRevsConditionalAPIModules() { |
605 | | - global $wgAPIModules, $wgAPIListModules; |
606 | | - if ( FlaggedRevs::useOnlyIfProtected() ) { |
| 639 | + global $wgAPIModules, $wgAPIListModules, $wgFlaggedRevsProtection; |
| 640 | + if ( $wgFlaggedRevsProtection ) { |
607 | 641 | $wgAPIModules['stabilize'] = 'ApiStabilizeProtect'; |
608 | 642 | } else { |
609 | 643 | $wgAPIModules['stabilize'] = 'ApiStabilizeGeneral'; |
— | — | @@ -613,8 +647,8 @@ |
614 | 648 | } |
615 | 649 | |
616 | 650 | function efSetFlaggedRevsConditionalRights() { |
617 | | - global $wgGroupPermissions, $wgFlaggedRevsAutoconfirm; |
618 | | - if ( FlaggedRevs::useOnlyIfProtected() ) { |
| 651 | + global $wgGroupPermissions, $wgFlaggedRevsProtection; |
| 652 | + if ( $wgFlaggedRevsProtection ) { |
619 | 653 | // Removes sp:ListGroupRights cruft |
620 | 654 | if ( isset( $wgGroupPermissions['editor'] ) ) { |
621 | 655 | unset( $wgGroupPermissions['editor']['unreviewedpages'] ); |
— | — | @@ -623,10 +657,6 @@ |
624 | 658 | unset( $wgGroupPermissions['reviewer']['unreviewedpages'] ); |
625 | 659 | } |
626 | 660 | } |
627 | | - if ( !empty( $wgFlaggedRevsAutoconfirm ) ) { |
628 | | - # Implicit autoreview group |
629 | | - $wgGroupPermissions['autoreview']['autoreview'] = true; |
630 | | - } |
631 | 661 | } |
632 | 662 | |
633 | 663 | function efSetFlaggedRevsConditionalPreferences() { |
Index: trunk/extensions/FlaggedRevs/dataclasses/FlaggedRevs.hooks.php |
— | — | @@ -679,12 +679,12 @@ |
680 | 680 | * Check if a user meets the edit spacing requirements. |
681 | 681 | * If the user does not, return a *lower bound* number of seconds |
682 | 682 | * that must elapse for it to be possible for the user to meet them. |
| 683 | + * @param User $user |
683 | 684 | * @param int $spacingReq days apart (of edit points) |
684 | 685 | * @param int $pointsReq number of edit points |
685 | | - * @param User $user |
686 | 686 | * @return mixed (true if passed, int seconds on failure) |
687 | 687 | */ |
688 | | - protected static function editSpacingCheck( $spacingReq, $pointsReq, $user ) { |
| 688 | + protected static function editSpacingCheck( User $user, $spacingReq, $pointsReq ) { |
689 | 689 | $benchmarks = 0; // actual edit points |
690 | 690 | # Convert days to seconds... |
691 | 691 | $spacingReq = $spacingReq * 24 * 3600; |
— | — | @@ -743,7 +743,7 @@ |
744 | 744 | /** |
745 | 745 | * Checks if $user was previously blocked |
746 | 746 | */ |
747 | | - public static function wasPreviouslyBlocked( $user ) { |
| 747 | + protected static function wasPreviouslyBlocked( $user ) { |
748 | 748 | $dbr = wfGetDB( DB_SLAVE ); |
749 | 749 | return (bool)$dbr->selectField( 'logging', '1', |
750 | 750 | array( |
— | — | @@ -756,6 +756,36 @@ |
757 | 757 | ); |
758 | 758 | } |
759 | 759 | |
| 760 | + protected static function recentEditCount( $uid, $seconds, $limit ) { |
| 761 | + $dbr = wfGetDB( DB_SLAVE ); |
| 762 | + # Get cutoff timestamp (edits that are too recent) |
| 763 | + $encCutoff = $dbr->addQuotes( $dbr->timestamp( time() - $seconds ) ); |
| 764 | + # Check all recent edits... |
| 765 | + $res = $dbr->select( 'revision', '1', |
| 766 | + array( 'rev_user' => $uid, "rev_timestamp > $encCutoff" ), |
| 767 | + __METHOD__, |
| 768 | + array( 'LIMIT' => $limit + 1 ) // hit as few rows as possible |
| 769 | + ); |
| 770 | + return $dbr->numRows( $res ); |
| 771 | + } |
| 772 | + |
| 773 | + protected static function recentContentEditCount( $uid, $seconds, $limit ) { |
| 774 | + $dbr = wfGetDB( DB_SLAVE ); |
| 775 | + # Get cutoff timestamp (edits that are too recent) |
| 776 | + $encCutoff = $dbr->addQuotes( $dbr->timestamp( time() - $seconds ) ); |
| 777 | + # Check all recent content edits... |
| 778 | + $res = $dbr->select( array( 'revision', 'page' ), '1', |
| 779 | + array( 'rev_user' => $uid, |
| 780 | + "rev_timestamp > $encCutoff", |
| 781 | + 'rev_page = page_id', |
| 782 | + 'page_namespace' => MWNamespace::getContentNamespaces() ), |
| 783 | + __METHOD__, |
| 784 | + array( 'LIMIT' => $limit + 1, |
| 785 | + 'USE INDEX' => array( 'revision' => 'user_timestamp' ) ) |
| 786 | + ); |
| 787 | + return $dbr->numRows( $res ); |
| 788 | + } |
| 789 | + |
760 | 790 | /** |
761 | 791 | * Grant 'autoreview' rights to users with the 'bot' right |
762 | 792 | */ |
— | — | @@ -787,9 +817,6 @@ |
788 | 818 | if ( $changed ) { |
789 | 819 | FRUserCounters::saveUserParams( $user->getId(), $p ); // save any updates |
790 | 820 | } |
791 | | - if ( is_array( $wgFlaggedRevsAutopromote ) ) { |
792 | | - self::maybeMakeEditor( $user, $p, $wgFlaggedRevsAutopromote ); |
793 | | - } |
794 | 821 | return true; |
795 | 822 | } |
796 | 823 | |
— | — | @@ -803,27 +830,32 @@ |
804 | 831 | switch( $cond ) { |
805 | 832 | case APCOND_FR_EDITSUMMARYCOUNT: |
806 | 833 | $p = FRUserCounters::getParams( $user ); |
807 | | - $result = ( is_array( $p ) && $p['editComments'] >= $params[0] ); |
| 834 | + $result = ( $p && $p['editComments'] >= $params[0] ); |
808 | 835 | break; |
809 | 836 | case APCOND_FR_NEVERBOCKED: |
810 | | - $key = wfMemcKey( 'flaggedrevs', 'autopromote-blocked-ok', $user->getId() ); |
811 | | - $val = $wgMemc->get( $key ); |
812 | | - if ( $val === 'true' ) { |
813 | | - $result = true; // passed |
814 | | - } elseif ( $val === 'false' ) { |
| 837 | + if ( $user->isBlocked() ) { |
815 | 838 | $result = false; // failed |
816 | 839 | } else { |
817 | | - # Hit the DB only if the result is not cached... |
818 | | - $result = !self::wasPreviouslyBlocked( $user ); |
819 | | - $wgMemc->set( $key, $result ? 'true' : 'false', 3600 * 24 * 7 ); // cache results |
| 840 | + $key = wfMemcKey( 'flaggedrevs', 'autopromote-blocked', $user->getId() ); |
| 841 | + $val = $wgMemc->get( $key ); |
| 842 | + if ( $val === 'true' ) { |
| 843 | + $result = true; // passed |
| 844 | + } elseif ( $val === 'false' ) { |
| 845 | + $result = false; // failed |
| 846 | + } else { |
| 847 | + # Hit the DB only if the result is not cached... |
| 848 | + $result = !self::wasPreviouslyBlocked( $user ); |
| 849 | + $wgMemc->set( $key, $result ? 'true' : 'false', 3600 * 24 * 7 ); |
| 850 | + } |
820 | 851 | } |
821 | 852 | break; |
822 | 853 | case APCOND_FR_UNIQUEPAGECOUNT: |
823 | 854 | $p = FRUserCounters::getParams( $user ); |
824 | | - $result = ( is_array( $p ) && $p['uniqueContentPages'] >= $params[0] ); |
| 855 | + $result = ( $p && $p['uniqueContentPages'] >= $params[0] ); |
825 | 856 | break; |
826 | 857 | case APCOND_FR_EDITSPACING: |
827 | | - $key = wfMemcKey( 'flaggedrevs', 'autopromote-spacing-ok', $user->getId() ); |
| 858 | + $key = wfMemcKey( 'flaggedrevs', 'autopromote-editspacing', |
| 859 | + $user->getId(), $params[0], $params[1] ); |
828 | 860 | $val = $wgMemc->get( $key ); |
829 | 861 | if ( $val === 'true' ) { |
830 | 862 | $result = true; // passed |
— | — | @@ -831,7 +863,7 @@ |
832 | 864 | $result = false; // failed |
833 | 865 | } else { |
834 | 866 | # Hit the DB only if the result is not cached... |
835 | | - $pass = self::editSpacingCheck( $params[0], $params[1], $user ); |
| 867 | + $pass = self::editSpacingCheck( $user, $params[0], $params[1] ); |
836 | 868 | # Make a key to store the results |
837 | 869 | if ( $pass === true ) { |
838 | 870 | $wgMemc->set( $key, 'true', 14 * 24 * 3600 ); |
— | — | @@ -841,147 +873,55 @@ |
842 | 874 | $result = ( $pass === true ); |
843 | 875 | } |
844 | 876 | break; |
| 877 | + case APCOND_FR_EDITCOUNT: |
| 878 | + # $maxNew is the *most* edits that can be too recent |
| 879 | + $maxNew = $user->getEditCount() - $params[0]; |
| 880 | + if ( $maxNew < 0 ) { |
| 881 | + $result = false; // doesn't meet count even *with* recent edits |
| 882 | + } elseif ( $params[1] <= 0 ) { |
| 883 | + $result = true; // passed; we aren't excluding any recent edits |
| 884 | + } else { |
| 885 | + # Check all recent edits... |
| 886 | + $n = self::recentEditCount( $user->getId(), $params[1], $maxNew ); |
| 887 | + $result = ( $n <= $maxNew ); |
| 888 | + } |
| 889 | + break; |
845 | 890 | case APCOND_FR_CONTENTEDITCOUNT: |
846 | 891 | $p = FRUserCounters::getParams( $user ); |
847 | | - $result = ( is_array( $p ) && $p['totalContentEdits'] >= $params[0] ); |
| 892 | + if ( !$p ) { |
| 893 | + $result = false; |
| 894 | + } else { |
| 895 | + # $maxNew is the *most* edits that can be too recent |
| 896 | + $maxNew = $p['totalContentEdits'] - $params[0]; |
| 897 | + if ( $maxNew < 0 ) { |
| 898 | + $result = false; // doesn't meet count even *with* recent edits |
| 899 | + } elseif ( $params[1] <= 0 ) { |
| 900 | + $result = true; // passed; we aren't excluding any recent edits |
| 901 | + } else { |
| 902 | + # Check all recent content edits... |
| 903 | + $n = self::recentContentEditCount( $user->getId(), $params[1], $maxNew ); |
| 904 | + $result = ( $n <= $maxNew ); |
| 905 | + } |
| 906 | + } |
848 | 907 | break; |
849 | 908 | case APCOND_FR_CHECKEDEDITCOUNT: |
850 | | - $result = self::reviewedEditsCheck( $user, $params[0] ); |
| 909 | + $result = self::reviewedEditsCheck( $user, $params[0], $params[1] ); |
851 | 910 | break; |
| 911 | + case APCOND_FR_USERPAGEBYTES: |
| 912 | + $result = ( !$params[0] || $user->getUserPage()->getLength() >= $params[0] ); |
| 913 | + break; |
| 914 | + case APCOND_FR_MAXREVERTEDEDITRATIO: |
| 915 | + $p = FRUserCounters::getParams( $user ); |
| 916 | + $result = ( $p && $params[0]*$user->getEditCount() >= $p['revertedEdits'] ); |
| 917 | + break; |
| 918 | + case APCOND_FR_NEVERDEMOTED: // b/c |
| 919 | + $p = FRUserCounters::getParams( $user ); |
| 920 | + $result = ( $p && !$p['demoted'] ); |
| 921 | + break; |
852 | 922 | } |
853 | 923 | return true; |
854 | 924 | } |
855 | 925 | |
856 | | - /** |
857 | | - * Autopromotes user according to the setting in $wgFlaggedRevsAutopromote. |
858 | | - * @param $user User |
859 | | - * @param $p array user tallies |
860 | | - * @param $conds array $wgFlaggedRevsAutopromote |
861 | | - */ |
862 | | - protected static function maybeMakeEditor( User $user, array $p, array $conds ) { |
863 | | - global $wgMemc, $wgContentNamespaces; |
864 | | - $groups = $user->getGroups(); // current groups |
865 | | - $regTime = wfTimestampOrNull( TS_UNIX, $user->getRegistration() ); |
866 | | - if ( |
867 | | - !$user->getId() || |
868 | | - # Do not give this to current holders |
869 | | - in_array( 'editor', $groups ) || |
870 | | - # Do not give this right to bots |
871 | | - $user->isAllowed( 'bot' ) || |
872 | | - # Do not re-add status if it was previously removed! |
873 | | - ( isset( $p['demoted'] ) && $p['demoted'] ) || |
874 | | - # Check if user edited enough unique pages |
875 | | - $conds['uniqueContentPages'] > count( $p['uniqueContentPages'] ) || |
876 | | - # Check edit summary usage |
877 | | - $conds['editComments'] > $p['editComments'] || |
878 | | - # Check reverted edits |
879 | | - $conds['maxRevertedEditRatio']*$user->getEditCount() < $p['revertedEdits'] || |
880 | | - # Check user edit count |
881 | | - $conds['edits'] > $user->getEditCount() || |
882 | | - # Check account age |
883 | | - ( $regTime && $conds['days'] > ( ( time() - $regTime ) / 86400 ) ) || |
884 | | - # See if the page actually has sufficient content... |
885 | | - $conds['userpageBytes'] > $user->getUserPage()->getLength() || |
886 | | - # Don't grant to currently blocked users... |
887 | | - $user->isBlocked() |
888 | | - ) { |
889 | | - return true; // not ready |
890 | | - } |
891 | | - # User needs to meet 'totalContentEdits' OR 'totalCheckedEdits' |
892 | | - $failedContentEdits = ( $conds['totalContentEdits'] > $p['totalContentEdits'] ); |
893 | | - |
894 | | - # More expensive checks below... |
895 | | - # Check if results are cached to avoid DB queries |
896 | | - $APSkipKey = wfMemcKey( 'flaggedrevs', 'autopromote-skip', $user->getId() ); |
897 | | - if ( $wgMemc->get( $APSkipKey ) === 'true' ) { |
898 | | - return true; |
899 | | - } |
900 | | - # Check if user was ever blocked before |
901 | | - if ( $conds['neverBlocked'] && self::wasPreviouslyBlocked( $user ) ) { |
902 | | - $wgMemc->set( $APSkipKey, 'true', 3600 * 24 * 7 ); // cache results |
903 | | - return true; |
904 | | - } |
905 | | - $dbr = wfGetDB( DB_SLAVE ); |
906 | | - $cutoff_ts = 0; |
907 | | - # Check to see if the user has enough non-"last minute" edits. |
908 | | - if ( $conds['excludeLastDays'] > 0 ) { |
909 | | - $minDiffAll = $user->getEditCount() - $conds['edits'] + 1; |
910 | | - # Get cutoff timestamp |
911 | | - $cutoff_ts = time() - 86400*$conds['excludeLastDays']; |
912 | | - $encCutoff = $dbr->addQuotes( $dbr->timestamp( $cutoff_ts ) ); |
913 | | - # Check all recent edits... |
914 | | - $res = $dbr->select( 'revision', '1', |
915 | | - array( 'rev_user' => $user->getId(), "rev_timestamp > $encCutoff" ), |
916 | | - __METHOD__, |
917 | | - array( 'LIMIT' => $minDiffAll ) |
918 | | - ); |
919 | | - if ( $dbr->numRows( $res ) >= $minDiffAll ) { |
920 | | - return true; // delay promotion |
921 | | - } |
922 | | - # Check recent content edits... |
923 | | - if ( !$failedContentEdits && $wgContentNamespaces ) { |
924 | | - $minDiffContent = $p['totalContentEdits'] - $conds['totalContentEdits'] + 1; |
925 | | - $res = $dbr->select( array( 'revision', 'page' ), '1', |
926 | | - array( 'rev_user' => $user->getId(), |
927 | | - "rev_timestamp > $encCutoff", |
928 | | - 'rev_page = page_id', |
929 | | - 'page_namespace' => $wgContentNamespaces ), |
930 | | - __METHOD__, |
931 | | - array( 'USE INDEX' => array( 'revision' => 'user_timestamp' ), |
932 | | - 'LIMIT' => $minDiffContent ) |
933 | | - ); |
934 | | - if ( $dbr->numRows( $res ) >= $minDiffContent ) { |
935 | | - $failedContentEdits = true; // totalCheckedEdits needed |
936 | | - } |
937 | | - } |
938 | | - } |
939 | | - # Check for edit spacing. This lets us know that the account has |
940 | | - # been used over N different days, rather than all in one lump. |
941 | | - if ( $conds['spacing'] > 0 && $conds['benchmarks'] > 1 ) { |
942 | | - $pass = self::editSpacingCheck( $conds['spacing'], $conds['benchmarks'], $user ); |
943 | | - if ( $pass !== true ) { |
944 | | - $wgMemc->set( $APSkipKey, 'true', $pass /* wait time */ ); // cache results |
945 | | - return true; |
946 | | - } |
947 | | - } |
948 | | - # Check if there are enough implicitly reviewed edits |
949 | | - if ( $failedContentEdits && $conds['totalCheckedEdits'] > 0 ) { |
950 | | - if ( !self::reviewedEditsCheck( $user, $conds['totalCheckedEdits'], $cutoff_ts ) ) { |
951 | | - return true; |
952 | | - } |
953 | | - } |
954 | | - |
955 | | - # Add editor rights... |
956 | | - $newGroups = $groups; |
957 | | - array_push( $newGroups, 'editor' ); |
958 | | - $log = new LogPage( 'rights', false /* $rc */ ); |
959 | | - $log->addEntry( 'rights', |
960 | | - $user->getUserPage(), |
961 | | - wfMsgForContent( 'rights-editor-autosum' ), |
962 | | - array( implode( ', ', $groups ), implode( ', ', $newGroups ) ) |
963 | | - ); |
964 | | - $user->addGroup( 'editor' ); |
965 | | - |
966 | | - return true; |
967 | | - } |
968 | | - |
969 | | - /** |
970 | | - * Record demotion so that auto-promote will be disabled |
971 | | - */ |
972 | | - public static function recordDemote( $user, array $addgroup, array $removegroup ) { |
973 | | - if ( $removegroup && in_array( 'editor', $removegroup ) ) { |
974 | | - $dbName = false; // this wiki |
975 | | - // Cross-wiki rights changes... |
976 | | - if ( $user instanceof UserRightsProxy ) { |
977 | | - $dbName = $user->getDBName(); // use foreign DB of the user |
978 | | - } |
979 | | - $p = FRUserCounters::getUserParams( $user->getId(), FR_FOR_UPDATE, $dbName ); |
980 | | - $p['demoted'] = 1; |
981 | | - FRUserCounters::saveUserParams( $user->getId(), $p, $dbName ); |
982 | | - } |
983 | | - return true; |
984 | | - } |
985 | | - |
986 | 926 | public static function stableDumpQuery( array &$tables, array &$opts, array &$join ) { |
987 | 927 | $namespaces = FlaggedRevs::getReviewNamespaces(); |
988 | 928 | if ( $namespaces ) { |
— | — | @@ -997,9 +937,11 @@ |
998 | 938 | return false; // final |
999 | 939 | } |
1000 | 940 | |
1001 | | - public static function gnsmQueryModifier( array $params, array &$joins, array &$conditions, array &$tables ) { |
| 941 | + public static function gnsmQueryModifier( |
| 942 | + array $params, array &$joins, array &$conditions, array &$tables |
| 943 | + ) { |
1002 | 944 | $filterSet = array( GoogleNewsSitemap::OPT_ONLY => true, |
1003 | | - GoogleNewsSitemap::OPT_EXCLUDE => true |
| 945 | + GoogleNewsSitemap::OPT_EXCLUDE => true |
1004 | 946 | ); |
1005 | 947 | # Either involves the same JOIN here... |
1006 | 948 | if ( isset( $filterSet[ $params['stable'] ] ) || isset( $filterSet[ $params['quality'] ] ) ) { |
Index: trunk/extensions/FlaggedRevs/FlaggedRevsDefines.php |
— | — | @@ -29,11 +29,15 @@ |
30 | 30 | define( 'FR_SHOW_STABLE_NEVER', 2 ); |
31 | 31 | |
32 | 32 | # Autopromote conds (F=70,R=82) |
33 | | -# @TODO: move these 5 to core |
| 33 | +# @TODO: move these 6 to core |
34 | 34 | define( 'APCOND_FR_EDITSUMMARYCOUNT', 70821 ); |
35 | 35 | define( 'APCOND_FR_NEVERBOCKED', 70822 ); |
36 | 36 | define( 'APCOND_FR_UNIQUEPAGECOUNT', 70823 ); |
37 | | -define( 'APCOND_FR_EDITSPACING', 70824 ); |
38 | | -define( 'APCOND_FR_CONTENTEDITCOUNT', 70825 ); |
| 37 | +define( 'APCOND_FR_CONTENTEDITCOUNT', 70824 ); |
| 38 | +define( 'APCOND_FR_USERPAGEBYTES', 70825 ); |
| 39 | +define( 'APCOND_FR_EDITCOUNT', 70826 ); |
39 | 40 | |
40 | | -define( 'APCOND_FR_CHECKEDEDITCOUNT', 70826 ); |
| 41 | +define( 'APCOND_FR_EDITSPACING', 70827 ); |
| 42 | +define( 'APCOND_FR_CHECKEDEDITCOUNT', 70828 ); |
| 43 | +define( 'APCOND_FR_MAXREVERTEDEDITRATIO', 70829 ); |
| 44 | +define( 'APCOND_FR_NEVERDEMOTED', 70830 ); |