Index: trunk/extensions/FlaggedRevs/FRUserCounters.php |
— | — | @@ -6,31 +6,27 @@ |
7 | 7 | /** |
8 | 8 | * Get params for a user |
9 | 9 | * @param int $uid |
10 | | - * @param string $DBName, optional wiki name |
11 | | - * @returns array $params |
| 10 | + * @param int $flags FR_MASTER, FR_FOR_UPDATE |
| 11 | + * @param string $dBName, optional wiki name |
| 12 | + * @returns array |
12 | 13 | */ |
13 | | - public static function getUserParams( $uid, $DBName = false ) { |
14 | | - $dbw = wfGetDB( DB_MASTER, array(), $DBName ); |
15 | | - $row = $dbw->selectRow( 'flaggedrevs_promote', |
16 | | - 'frp_user_params', |
17 | | - array( 'frp_user_id' => $uid ), |
18 | | - __METHOD__ |
19 | | - // 'FOR UPDATE' |
20 | | - ); |
21 | | - # Parse params |
22 | | - $p = array(); // init |
| 14 | + public static function getUserParams( $uid, $flags = 0, $dBName = false ) { |
| 15 | + $p = array(); |
| 16 | + $row = self::fetchParamsRow( $uid, $flags, $dBName ); |
23 | 17 | if ( $row ) { |
24 | | - $flatPars = explode( "\n", trim( $row->frp_user_params ) ); |
25 | | - foreach ( $flatPars as $pair ) { |
26 | | - $m = explode( '=', trim( $pair ), 2 ); |
27 | | - $key = $m[0]; |
28 | | - $value = isset( $m[1] ) ? $m[1] : null; |
29 | | - $p[$key] = $value; |
30 | | - } |
| 18 | + $p = self::expandParams( $row->frp_user_params ); |
31 | 19 | } |
32 | | - # Initialize fields as needed... |
| 20 | + self::setUnitializedFields( $p ); |
| 21 | + return $p; |
| 22 | + } |
| 23 | + |
| 24 | + /** |
| 25 | + * Initializes unset param fields to their starting values |
| 26 | + * @param &array $p |
| 27 | + */ |
| 28 | + protected static function setUnitializedFields( array &$p ) { |
33 | 29 | if ( !isset( $p['uniqueContentPages'] ) ) { |
34 | | - $p['uniqueContentPages'] = ''; |
| 30 | + $p['uniqueContentPages'] = array(); |
35 | 31 | } |
36 | 32 | if ( !isset( $p['totalContentEdits'] ) ) { |
37 | 33 | $p['totalContentEdits'] = 0; |
— | — | @@ -41,31 +37,94 @@ |
42 | 38 | if ( !isset( $p['revertedEdits'] ) ) { |
43 | 39 | $p['revertedEdits'] = 0; |
44 | 40 | } |
45 | | - return $p; |
46 | 41 | } |
47 | 42 | |
48 | 43 | /** |
| 44 | + * Get the params row for a user |
| 45 | + * @param int $uid |
| 46 | + * @param int $flags FR_MASTER, FR_FOR_UPDATE |
| 47 | + * @param string $dBName, optional wiki name |
| 48 | + * @returns mixed (false or Row) |
| 49 | + */ |
| 50 | + protected static function fetchParamsRow( $uid, $flags = 0, $dBName = false ) { |
| 51 | + $options = array(); |
| 52 | + if ( $flags & FR_MASTER || $flags & FR_FOR_UPDATE ) { |
| 53 | + $db = wfGetDB( DB_MASTER, array(), $dBName ); |
| 54 | + if ( $flags & FR_FOR_UPDATE ) $options[] = 'FOR UPDATE'; |
| 55 | + } else { |
| 56 | + $db = wfGetDB( DB_SLAVE, array(), $dBName ); |
| 57 | + } |
| 58 | + return $db->selectRow( 'flaggedrevs_promote', |
| 59 | + 'frp_user_params', |
| 60 | + array( 'frp_user_id' => $uid ), |
| 61 | + __METHOD__, |
| 62 | + $options |
| 63 | + ); |
| 64 | + } |
| 65 | + |
| 66 | + /** |
49 | 67 | * Save params for a user |
50 | 68 | * @param int $uid |
51 | 69 | * @param array $params |
52 | | - * @param string $DBName, optional wiki name |
| 70 | + * @param string $dBName, optional wiki name |
53 | 71 | * @returns bool success |
54 | 72 | */ |
55 | | - public static function saveUserParams( $uid, array $params, $DBName = false ) { |
56 | | - $flatParams = ''; |
57 | | - foreach ( $params as $key => $value ) { |
58 | | - $flatParams .= "{$key}={$value}\n"; |
59 | | - } |
60 | | - $dbw = wfGetDB( DB_MASTER, array(), $DBName ); |
| 73 | + public static function saveUserParams( $uid, array $params, $dBName = false ) { |
| 74 | + $dbw = wfGetDB( DB_MASTER, array(), $dBName ); |
61 | 75 | $row = $dbw->replace( 'flaggedrevs_promote', |
62 | 76 | array( 'frp_user_id' ), |
63 | | - array( 'frp_user_id' => $uid, 'frp_user_params' => trim( $flatParams ) ), |
| 77 | + array( 'frp_user_id' => $uid, |
| 78 | + 'frp_user_params' => self::flattenParams( $params ) ), |
64 | 79 | __METHOD__ |
65 | 80 | ); |
66 | 81 | return ( $dbw->affectedRows() > 0 ); |
67 | 82 | } |
68 | 83 | |
69 | 84 | /** |
| 85 | + * Flatten params for a user for DB storage |
| 86 | + * Note: param values must be integers |
| 87 | + * @param array $params |
| 88 | + * @returns string |
| 89 | + */ |
| 90 | + protected static function flattenParams( array $params ) { |
| 91 | + $flatRows = array(); |
| 92 | + foreach ( $params as $key => $value ) { |
| 93 | + if ( strpos( $key, '=' ) !== false || strpos( $key, "\n" ) !== false ) { |
| 94 | + throw new MWException( "flattenParams() - key cannot use '=' or newline" ); |
| 95 | + } |
| 96 | + if ( $key === 'uniqueContentPages' ) { // list |
| 97 | + $value = implode( ',', array_map( 'intval', $value ) ); |
| 98 | + } else { |
| 99 | + $value = intval( $value ); |
| 100 | + } |
| 101 | + $flatRows[] = trim( $key ) . '=' . $value; |
| 102 | + } |
| 103 | + return implode( "\n", $flatRows ); |
| 104 | + } |
| 105 | + |
| 106 | + /** |
| 107 | + * Expand params for a user from DB storage |
| 108 | + * @param string $flatPars |
| 109 | + * @returns array |
| 110 | + */ |
| 111 | + protected static function expandParams( $flatPars ) { |
| 112 | + $p = array(); // init |
| 113 | + $flatPars = explode( "\n", trim( $flatPars ) ); |
| 114 | + foreach ( $flatPars as $pair ) { |
| 115 | + $m = explode( '=', trim( $pair ), 2 ); |
| 116 | + $key = $m[0]; |
| 117 | + $value = isset( $m[1] ) ? $m[1] : null; |
| 118 | + if ( $key === 'uniqueContentPages' ) { // list |
| 119 | + $value = array_map( 'intval', explode( ',', $value ) ); |
| 120 | + } else { |
| 121 | + $value = intval( $value ); |
| 122 | + } |
| 123 | + $p[$key] = $value; |
| 124 | + } |
| 125 | + return $p; |
| 126 | + } |
| 127 | + |
| 128 | + /** |
70 | 129 | * Update users params array for a user on edit |
71 | 130 | * @param &array $params |
72 | 131 | * @param Article $article the article just edited |
— | — | @@ -77,7 +136,7 @@ |
78 | 137 | # Update any special counters for non-null revisions |
79 | 138 | $changed = false; |
80 | 139 | if ( $article->getTitle()->isContentPage() ) { |
81 | | - $pages = explode( ',', trim( $p['uniqueContentPages'] ) ); // page IDs |
| 140 | + $pages = $p['uniqueContentPages']; // page IDs |
82 | 141 | # Don't let this get bloated for no reason |
83 | 142 | $maxUniquePages = 50; // some flexibility |
84 | 143 | if ( is_array( $wgFlaggedRevsAutoconfirm ) && |
— | — | @@ -94,12 +153,12 @@ |
95 | 154 | && !in_array( $article->getId(), $pages ) ) |
96 | 155 | { |
97 | 156 | $pages[] = $article->getId(); |
98 | | - // Clear out any formatting garbage |
99 | | - $p['uniqueContentPages'] = preg_replace( '/^,/', '', implode( ',', $pages ) ); |
| 157 | + $p['uniqueContentPages'] = $pages; |
100 | 158 | } |
101 | 159 | $p['totalContentEdits'] += 1; |
102 | 160 | $changed = true; |
103 | 161 | } |
| 162 | + // Record non-automatic summary tally |
104 | 163 | if ( !preg_match( '/^\/\*.*\*\/$/', $summary ) ) { |
105 | 164 | $p['editComments'] += 1; |
106 | 165 | $changed = true; |
Index: trunk/extensions/FlaggedRevs/maintenance/updateAutoPromote.inc |
— | — | @@ -1,6 +1,5 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | | - |
5 | 4 | function update_autopromote() { |
6 | 5 | global $wgContentNamespaces, $wgFlaggedRevsAutopromote; |
7 | 6 | $batchSize = 50; |
— | — | @@ -23,7 +22,7 @@ |
24 | 23 | # Go through and clean up missing items, as well as correct fr_quality... |
25 | 24 | foreach( $res as $row ) { |
26 | 25 | $user = User::newFromRow( $row ); |
27 | | - $p = FRUserCounters::getUserParams( $user->getId() ); |
| 26 | + $p = FRUserCounters::getUserParams( $user->getId(), FR_FOR_UPDATE ); |
28 | 27 | $oldp = $p; |
29 | 28 | # Get edit comments used |
30 | 29 | $sres = $db->select( 'revision', '1', |
— | — | @@ -50,12 +49,11 @@ |
51 | 50 | __METHOD__, |
52 | 51 | array( 'LIMIT' => max($wgFlaggedRevsAutopromote['uniqueContentPages'],50) ) |
53 | 52 | ); |
54 | | - $uniquePages = array(); |
| 53 | + $p['uniqueContentPages'] = array(); |
55 | 54 | foreach( $sres as $row ) { |
56 | | - $uniquePages[] = $row->rev_page; |
| 55 | + $p['uniqueContentPages'][] = (int)$row->rev_page; |
57 | 56 | } |
58 | | - $p['uniqueContentPages'] = implode($uniquePages,','); |
59 | | - |
| 57 | + # Save the new params... |
60 | 58 | if( $oldp != $p ) { |
61 | 59 | FRUserCounters::saveUserParams( $user->getId(), $p ); |
62 | 60 | $changed++; |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.hooks.php |
— | — | @@ -960,7 +960,7 @@ |
961 | 961 | # Mark when a user reverts another user, but not self-reverts |
962 | 962 | $badUserId = $badRev->getRawUser(); |
963 | 963 | if ( $badUserId && $user->getId() != $badUserId ) { |
964 | | - $p = FRUserCounters::getUserParams( $badUserId ); |
| 964 | + $p = FRUserCounters::getUserParams( $badUserId, FR_FOR_UPDATE ); |
965 | 965 | if ( !isset( $p['revertedEdits'] ) ) { |
966 | 966 | $p['revertedEdits'] = 0; |
967 | 967 | } |
— | — | @@ -983,7 +983,7 @@ |
984 | 984 | if ( $badRev && $badRev->getRawUser() |
985 | 985 | && $badRev->getRawUser() != $rev->getRawUser() ) |
986 | 986 | { |
987 | | - $p = FRUserCounters::getUserParams( $badRev->getRawUser() ); |
| 987 | + $p = FRUserCounters::getUserParams( $badRev->getRawUser(), FR_FOR_UPDATE ); |
988 | 988 | if ( !isset( $p['revertedEdits'] ) ) { |
989 | 989 | $p['revertedEdits'] = 0; |
990 | 990 | } |
— | — | @@ -1087,7 +1087,7 @@ |
1088 | 1088 | $totalCheckedEditsNeeded = true; |
1089 | 1089 | } |
1090 | 1090 | # Check if user edited enough unique pages |
1091 | | - $pages = explode( ',', trim( $p['uniqueContentPages'] ) ); // page IDs |
| 1091 | + $pages = $p['uniqueContentPages']; // page IDs |
1092 | 1092 | if ( $wgFlaggedRevsAutoconfirm['uniqueContentPages'] > count( $pages ) ) { |
1093 | 1093 | return true; |
1094 | 1094 | } |
— | — | @@ -1178,7 +1178,7 @@ |
1179 | 1179 | } elseif ( !$wgFlaggedRevsAutopromote && !$wgFlaggedRevsAutoconfirm ) { |
1180 | 1180 | return true; |
1181 | 1181 | } |
1182 | | - $p = FRUserCounters::getUserParams( $user->getId() ); |
| 1182 | + $p = FRUserCounters::getUserParams( $user->getId(), FR_FOR_UPDATE ); |
1183 | 1183 | $changed = FRUserCounters::updateUserParams( $p, $article, $summary ); |
1184 | 1184 | # Save any updates to user params |
1185 | 1185 | if ( $changed ) { |
— | — | @@ -1210,7 +1210,7 @@ |
1211 | 1211 | $totalCheckedEditsNeeded = true; |
1212 | 1212 | } |
1213 | 1213 | # Check if user edited enough unique pages |
1214 | | - $pages = explode( ',', trim( $p['uniqueContentPages'] ) ); // page IDs |
| 1214 | + $pages = $p['uniqueContentPages']; // page IDs |
1215 | 1215 | if ( $wgFlaggedRevsAutopromote['uniqueContentPages'] > count( $pages ) ) { |
1216 | 1216 | return true; |
1217 | 1217 | } |
— | — | @@ -1370,19 +1370,16 @@ |
1371 | 1371 | /** |
1372 | 1372 | * Record demotion so that auto-promote will be disabled |
1373 | 1373 | */ |
1374 | | - public static function recordDemote( $u, $addgroup, $removegroup ) { |
| 1374 | + public static function recordDemote( $user, array $addgroup, array $removegroup ) { |
1375 | 1375 | if ( $removegroup && in_array( 'editor', $removegroup ) ) { |
1376 | | - // Cross-wiki rights change |
1377 | | - if ( $u instanceof UserRightsProxy ) { |
1378 | | - $params = FRUserCounters::getUserParams( $u->getId(), $u->getDBName() ); |
1379 | | - $params['demoted'] = 1; |
1380 | | - FRUserCounters::saveUserParams( $u->getId(), $params, $u->getDBName() ); |
1381 | | - // On-wiki rights change |
1382 | | - } else { |
1383 | | - $params = FRUserCounters::getUserParams( $u->getId() ); |
1384 | | - $params['demoted'] = 1; |
1385 | | - FRUserCounters::saveUserParams( $u->getId(), $params ); |
| 1376 | + $dbName = false; // this wiki |
| 1377 | + // Cross-wiki rights changes... |
| 1378 | + if ( $user instanceof UserRightsProxy ) { |
| 1379 | + $dbName = $user->getDBName(); // use foreign DB of the user |
1386 | 1380 | } |
| 1381 | + $p = FRUserCounters::getUserParams( $user->getId(), FR_FOR_UPDATE, $dbName ); |
| 1382 | + $p['demoted'] = 1; |
| 1383 | + FRUserCounters::saveUserParams( $user->getId(), $p, $dbName ); |
1387 | 1384 | } |
1388 | 1385 | return true; |
1389 | 1386 | } |