Index: trunk/extensions/SecurePoll/cli/wm-scripts/populateBv2009EditCount.php |
— | — | @@ -0,0 +1,53 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * have made at least 600 edits before 01 June 2009 across Wikimedia wikis (edits on several wikis can be combined if your accounts are unified into a global account); and |
| 6 | + * have made at least 50 edits between 01 January and 01 July 2009. |
| 7 | + */ |
| 8 | + |
| 9 | +require( dirname(__FILE__) . '/../cli.inc' ); |
| 10 | +$dbr = wfGetDB( DB_SLAVE ); |
| 11 | +$dbw = wfGetDB( DB_MASTER ); |
| 12 | + |
| 13 | + |
| 14 | +$maxUser = $dbr->selectField( 'user', 'MAX(user_id)', false ); |
| 15 | +$beforeTime = '20090601000000'; |
| 16 | +$betweenTime = array( '20090101000000', '20090701000000' ); |
| 17 | +$fname = 'populatebv2009EditCount'; |
| 18 | + |
| 19 | +for ( $userId = 1; $userId <= $maxUser; $userId++ ) { |
| 20 | + $exists = $dbr->selectField( 'user', '1', array( 'user_id' => $userId ) ); |
| 21 | + if ( !$exists ) { |
| 22 | + continue; |
| 23 | + } |
| 24 | + |
| 25 | + $longEdits = $dbr->selectField( 'revision', 'COUNT(*)', |
| 26 | + array( |
| 27 | + 'rev_user' => $userId, |
| 28 | + 'rev_timestamp < ' . $dbr->addQuotes( $beforeTime ) |
| 29 | + ), $fname ); |
| 30 | + |
| 31 | + $shortEdits = $dbr->selectField( 'revision', 'COUNT(*)', |
| 32 | + array( |
| 33 | + 'rev_user' => $userId, |
| 34 | + 'rev_timestamp BETWEEN ' . $dbr->addQuotes( $betweenTime[0] ) . |
| 35 | + ' AND ' . $dbr->addQuotes( $betweenTime[1] ) |
| 36 | + ), |
| 37 | + $fname |
| 38 | + ); |
| 39 | + |
| 40 | + if ( $longEdits !== 0 || $shortEdits !== 0 ) { |
| 41 | + $dbw->insert( 'bv2009_edits', |
| 42 | + array( |
| 43 | + 'bv_user' => $userId, |
| 44 | + 'bv_long_edits' => $longEdits, |
| 45 | + 'bv_short_edits' => $shortEdits |
| 46 | + ), |
| 47 | + $fname |
| 48 | + ); |
| 49 | + $numUsers++; |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +echo wfWikiID() . ": $numUsers users added\n"; |
| 54 | + |
Property changes on: trunk/extensions/SecurePoll/cli/wm-scripts/populateBv2009EditCount.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 55 | + native |
Index: trunk/extensions/SecurePoll/cli/wm-scripts/voterList-bv2009.php |
— | — | @@ -0,0 +1,134 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +require( dirname( __FILE__ ) . '/../cli.inc' ); |
| 5 | +$dbr = wfGetDB( DB_SLAVE ); |
| 6 | +$dbw = wfGetDB( DB_MASTER ); |
| 7 | +$fname = 'voterList-bv2009.php'; |
| 8 | + |
| 9 | +if ( !$wgCentralAuthDatabase ) { |
| 10 | + echo wfWikiID() . ": CentralAuth not active, skipping\n"; |
| 11 | + exit( 0 ); |
| 12 | +} |
| 13 | + |
| 14 | +$dbw->delete( 'securepoll_lists', array( 'li_name' => 'board-vote-2009' ), $fname ); |
| 15 | + |
| 16 | +$userId = 0; |
| 17 | +$numQualified = 0; |
| 18 | +while ( true ) { |
| 19 | + $res = $dbr->select( 'user', array( 'user_id', 'user_name' ), |
| 20 | + array( 'user_id > ' . $dbr->addQuotes( $userId ) ), |
| 21 | + __METHOD__, |
| 22 | + array( 'LIMIT' => 1000, 'ORDER BY' => 'user_id' ) ); |
| 23 | + if ( !$res->numRows() ) { |
| 24 | + break; |
| 25 | + } |
| 26 | + |
| 27 | + $users = array(); |
| 28 | + foreach ( $res as $row ) { |
| 29 | + $users[$row->user_id] = $row->user_name; |
| 30 | + $userId = $row->user_id; |
| 31 | + } |
| 32 | + $qualifieds = spGetQualifiedUsers( $users ); |
| 33 | + $insertBatch = array(); |
| 34 | + foreach ( $qualifieds as $id => $name ) { |
| 35 | + $insertBatch[] = array( |
| 36 | + 'li_name' => 'board-vote-2009', |
| 37 | + 'li_member' => $id |
| 38 | + ); |
| 39 | + } |
| 40 | + if ( $insertBatch ) { |
| 41 | + $dbw->insert( 'securepoll_lists', $insertBatch, $fname ); |
| 42 | + $numQualified += count( $insertBatch ); |
| 43 | + } |
| 44 | +} |
| 45 | +echo wfWikiID() . " qualified \t$numQualified\n"; |
| 46 | + |
| 47 | +function spGetQualifiedUsers( $users ) { |
| 48 | + global $wgCentralAuthDatabase, $wgLocalDatabases; |
| 49 | + $dbc = wfGetDB( DB_SLAVE, array(), $wgCentralAuthDatabase ); |
| 50 | + $editCounts = array(); |
| 51 | + |
| 52 | + # Check local attachment |
| 53 | + $res = $dbc->select( 'localuser', array( 'lu_name' ), |
| 54 | + array( |
| 55 | + 'lu_wiki' => wfWikiID(), |
| 56 | + 'lu_name' => array_values( $users ) |
| 57 | + ), __METHOD__ ); |
| 58 | + |
| 59 | + $attached = array(); |
| 60 | + foreach ( $res as $row ) { |
| 61 | + $attached[] = $row->lu_name; |
| 62 | + $editCounts[$row->lu_name] = array( 0, 0 ); |
| 63 | + } |
| 64 | + $nonLocalUsers = array(); |
| 65 | + |
| 66 | + $localEditCounts = spGetEditCounts( wfGetDB( DB_SLAVE ), $users ); |
| 67 | + foreach ( $localEditCounts as $user => $counts ) { |
| 68 | + if ( $counts[0] == 0 ) { |
| 69 | + // No recent local edits, remove from consideration |
| 70 | + // This is just for efficiency, the user can vote somewhere else |
| 71 | + $nonLocalUsers[] = $user; |
| 72 | + } |
| 73 | + $editCounts[$user] = $counts; |
| 74 | + } |
| 75 | + $attached = array_diff( $attached, $nonLocalUsers ); |
| 76 | + |
| 77 | + # Check all global accounts |
| 78 | + if ( $attached ) { |
| 79 | + $res = $dbc->select( 'localuser', |
| 80 | + array( 'lu_name', 'lu_wiki' ), |
| 81 | + array( 'lu_name' => $attached ), |
| 82 | + __METHOD__ ); |
| 83 | + $foreignUsers = array(); |
| 84 | + foreach ( $res as $row ) { |
| 85 | + $foreignUsers[$row->lu_wiki][] = $row->lu_name; |
| 86 | + } |
| 87 | + |
| 88 | + foreach ( $foreignUsers as $wiki => $wikiUsers ) { |
| 89 | + if ( !in_array( $wiki, $wgLocalDatabases ) ) { |
| 90 | + continue; |
| 91 | + } |
| 92 | + $lb = wfGetLB( $wiki ); |
| 93 | + $db = $lb->getConnection( DB_SLAVE, array(), $wiki ); |
| 94 | + $foreignEditCounts = spGetEditCounts( $db, $wikiUsers ); |
| 95 | + $lb->reuseConnection( $db ); |
| 96 | + foreach ( $foreignEditCounts as $name => $count ) { |
| 97 | + $editCounts[$name][0] += $count[0]; |
| 98 | + $editCounts[$name][1] += $count[1]; |
| 99 | + } |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + $idsByUser = array_flip( $users ); |
| 104 | + $qualifiedUsers = array(); |
| 105 | + foreach ( $editCounts as $user => $count ) { |
| 106 | + if ( spIsQualified( $count[0], $count[1] ) ) { |
| 107 | + $id = $idsByUser[$user]; |
| 108 | + $qualifiedUsers[$id] = $user; |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + return $qualifiedUsers; |
| 113 | +} |
| 114 | + |
| 115 | +function spGetEditCounts( $db, $userNames ) { |
| 116 | + $res = $db->select( |
| 117 | + array( 'user', 'bv2009_edits' ), |
| 118 | + array( 'user_name', 'bv_long_edits', 'bv_short_edits' ), |
| 119 | + array( 'bv_user=user_id', 'user_name' => $userNames ), |
| 120 | + __METHOD__ ); |
| 121 | + $editCounts = array(); |
| 122 | + foreach ( $res as $row ) { |
| 123 | + $editCounts[$row->user_name] = array( $row->bv_short_edits, $row->bv_long_edits ); |
| 124 | + } |
| 125 | + foreach ( $userNames as $user ) { |
| 126 | + if ( !isset( $editCounts[$user] ) ) { |
| 127 | + $editCounts[$user] = array( 0, 0 ); |
| 128 | + } |
| 129 | + } |
| 130 | + return $editCounts; |
| 131 | +} |
| 132 | + |
| 133 | +function spIsQualified( $short, $long ) { |
| 134 | + return $short >= 50 && $long >= 600; |
| 135 | +} |
Property changes on: trunk/extensions/SecurePoll/cli/wm-scripts/voterList-bv2009.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 136 | + native |
Index: trunk/extensions/SecurePoll/cli/wm-scripts/dumpMetaTranslations.php |
— | — | @@ -0,0 +1,193 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +require( dirname( __FILE__ ) . '/../cli.inc' ); |
| 5 | + |
| 6 | +$spConf = array( |
| 7 | + 'numCandidates' => 18, |
| 8 | + 'baseId' => 17, |
| 9 | + 'basePage' => 'Board elections/2009/Vote interface', |
| 10 | + 'langs' => array( |
| 11 | + 'ar', |
| 12 | + 'ca', |
| 13 | + 'cs', |
| 14 | + 'de', |
| 15 | + 'el', |
| 16 | + 'en', |
| 17 | + 'eo', |
| 18 | + 'es', |
| 19 | + 'fi', |
| 20 | + 'fr', |
| 21 | + 'hr', |
| 22 | + 'hu', |
| 23 | + 'id', |
| 24 | + 'it', |
| 25 | + 'ja', |
| 26 | + 'jv', |
| 27 | + 'ms', |
| 28 | + 'nb', |
| 29 | + 'nl', |
| 30 | + 'pl', |
| 31 | + 'pt', |
| 32 | + 'pt-br', |
| 33 | + 'ru', |
| 34 | + 'sk', |
| 35 | + 'sv', |
| 36 | + 'tr', |
| 37 | + 'vi', |
| 38 | + 'zh-hans', |
| 39 | + 'zh-hant', |
| 40 | + ) |
| 41 | +); |
| 42 | + |
| 43 | +$header = <<<EOT |
| 44 | +<SecurePoll> |
| 45 | +<election> |
| 46 | +<configuration> |
| 47 | +<title>Wikimedia Board of Trustees Election, 2009</title> |
| 48 | +<ballot>preferential</ballot> |
| 49 | +<tally>schulze</tally> |
| 50 | +<primaryLang>en</primaryLang> |
| 51 | +<startDate>2009-07-28T08:00:00Z</startDate> |
| 52 | +<endDate>2009-08-10T23:59:59Z</endDate> |
| 53 | +<auth>remote-mw</auth> |
| 54 | +<id>{$spConf['baseId']}</id> |
| 55 | +<property name="admins">Pathoschild|Daniel|Yann|Dvortygirl|IAlex|Mardetanha|Werdna|Philippe Beaudette</property> |
| 56 | +<property name="not-blocked">1</property> |
| 57 | +<property name="not-bot">1</property> |
| 58 | +<property name="need-list">board-vote-2009</property> |
| 59 | +<property name="encrypt-type">gpg</property> |
| 60 | +<property name="remote-mw-script-path">https://secure.wikimedia.org/\$site/\$lang/w</property> |
| 61 | +<property name="shuffle-options">1</property> |
| 62 | +<property name="gpg-encrypt-key"><!-- insert key here --></property> |
| 63 | +<property name="gpg-sign-key"><!-- insert key here --></property> |
| 64 | + |
| 65 | + |
| 66 | +EOT; |
| 67 | + |
| 68 | +$allMessages = array(); |
| 69 | +foreach ( $spConf['langs'] as $lang ) { |
| 70 | + $messages = spGetMetaTranslations( $lang ); |
| 71 | + if ( $messages ) { |
| 72 | + $allMessages[$lang] = $messages; |
| 73 | + } else { |
| 74 | + fwrite( STDERR, "Messages not found for $lang\n" ); |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +$s = $header . |
| 79 | + spFormatEntityMessages( $allMessages, 'election' ) . |
| 80 | + "<question>\n" . |
| 81 | + "<id>" . ($spConf['baseId'] + 1) . "</id>\n" . |
| 82 | + "<message name=\"text\" lang=\"en\"></message>\n"; |
| 83 | + |
| 84 | +for ( $i = 1; $i <= $spConf['numCandidates']; $i++ ) { |
| 85 | + $s .= |
| 86 | + "<option>\n" . |
| 87 | + "<id>" . ( $i + $spConf['baseId'] + 1 ) . "</id>\n" . |
| 88 | + spFormatEntityMessages( $allMessages, "option_$i" ) . |
| 89 | + "</option>\n"; |
| 90 | +} |
| 91 | +$s .= "</question> |
| 92 | +</configuration> |
| 93 | +</election> |
| 94 | +</SecurePoll> |
| 95 | +"; |
| 96 | + |
| 97 | +echo $s; |
| 98 | +exit( 0 ); |
| 99 | +//------------------------------------------------------------------ |
| 100 | + |
| 101 | +function spGetMetaTranslations( $lang ) { |
| 102 | + global $spConf, $wgParser; |
| 103 | + $messages = array(); |
| 104 | + $titleText = "{$spConf['basePage']}/$lang"; |
| 105 | + $title = Title::newFromText( $titleText ); |
| 106 | + $numMessages = 0; |
| 107 | + if ( !$title ) { |
| 108 | + fwrite( STDERR, "Title invalid for lang $lang\n" ); |
| 109 | + return false; |
| 110 | + } |
| 111 | + $revision = Revision::newFromTitle( $title ); |
| 112 | + if ( !$revision ) { |
| 113 | + fwrite( STDERR, "Revision not found for page [[$titleText]]\n" ); |
| 114 | + return false; |
| 115 | + } |
| 116 | + $text = $revision->getText(); |
| 117 | + if ( $text === false ) { |
| 118 | + fwrite( STDERR, "Text not found for page [[$titleText]]\n" ); |
| 119 | + return false; |
| 120 | + } |
| 121 | + |
| 122 | + for ( $sectionIndex = 1; $sectionIndex <= 10; $sectionIndex++ ) { |
| 123 | + $section = $wgParser->getSection( $text, $sectionIndex, false ); |
| 124 | + if ( $section === false ) { |
| 125 | + break; |
| 126 | + } |
| 127 | + |
| 128 | + if ( !preg_match( '/^== *(.*?) *==\s*$/m', $section, $m ) ) { |
| 129 | + fwrite( STDERR, "Section header mismatch for section $sectionIndex of [[$titleText]]\n" ); |
| 130 | + continue; |
| 131 | + } |
| 132 | + $sectionName = strtolower( $m[1] ); |
| 133 | + $remainder = trim( substr( $section, strlen( $m[0] ) ) ); |
| 134 | + if ( strpos( $remainder, '<nowiki>' ) !== false ) { |
| 135 | + fwrite( STDERR, "Message $sectionName for $lang contains <nowiki>\n" ); |
| 136 | + continue; |
| 137 | + } |
| 138 | + |
| 139 | + $electionMsgMap = array( |
| 140 | + 'title' => 'title', |
| 141 | + 'introduction' => 'intro', |
| 142 | + 'jump text' => 'jump-text' |
| 143 | + ); |
| 144 | + if ( isset( $electionMsgMap[$sectionName] ) ) { |
| 145 | + $messages['election'][$electionMsgMap[$sectionName]] = $remainder; |
| 146 | + $numMessages++; |
| 147 | + continue; |
| 148 | + } |
| 149 | + |
| 150 | + if ( $sectionName == 'candidate text' ) { |
| 151 | + $i = 1; |
| 152 | + $lines = explode( "\n", $remainder ); |
| 153 | + foreach ( $lines as $line ) { |
| 154 | + if ( preg_match( '/^# *(.*)/', $line, $m ) ) { |
| 155 | + $messages["option_$i"]['text'] = $m[1]; |
| 156 | + $numMessages++; |
| 157 | + $i++; |
| 158 | + } |
| 159 | + } |
| 160 | + $i--; |
| 161 | + if ( $i !== $spConf['numCandidates'] ) { |
| 162 | + fwrite( STDERR, "Not enough candidates for $lang: $i/{$spConf['numCandidates']}\n" ); |
| 163 | + return false; |
| 164 | + } |
| 165 | + continue; |
| 166 | + } |
| 167 | + |
| 168 | + fwrite( STDERR, "Unrecognised section \"$sectionName\" in $lang\n" ); |
| 169 | + } |
| 170 | + |
| 171 | + fwrite( STDERR, "[[$titleText]]: found " . $numMessages . " messages\n" ); |
| 172 | + return $messages; |
| 173 | +} |
| 174 | + |
| 175 | +function spFormatEntityMessages( $messages, $entity ) { |
| 176 | + $s = ''; |
| 177 | + $targetEntity = $entity; |
| 178 | + foreach ( $messages as $lang => $langMsgs ) { |
| 179 | + foreach ( $langMsgs as $entity => $entityMsgs ) { |
| 180 | + if ( $entity === $targetEntity ) { |
| 181 | + foreach ( $entityMsgs as $key => $value ) { |
| 182 | + $s .= Xml::element( |
| 183 | + 'message', |
| 184 | + array( 'name' => $key, 'lang' => $lang ), |
| 185 | + $value |
| 186 | + ) . |
| 187 | + "\n"; |
| 188 | + } |
| 189 | + } |
| 190 | + } |
| 191 | + } |
| 192 | + return $s; |
| 193 | +} |
| 194 | + |
Property changes on: trunk/extensions/SecurePoll/cli/wm-scripts/dumpMetaTranslations.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 195 | + native |
Index: trunk/extensions/SecurePoll/cli/wm-scripts/bv2009_tables.sql |
— | — | @@ -0,0 +1,5 @@ |
| 2 | +CREATE TABLE bv2009_edits ( |
| 3 | + bv_user int not null primary key, |
| 4 | + bv_long_edits int not null, |
| 5 | + bv_short_edits int not null |
| 6 | +); |
Property changes on: trunk/extensions/SecurePoll/cli/wm-scripts/bv2009_tables.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 7 | + native |
Index: trunk/extensions/SecurePoll/cli/wm-scripts/README |
— | — | @@ -0,0 +1 @@ |
| 2 | +These are Wikimedia-specific scripts for voter lists, configuration and translation transfer. |
Property changes on: trunk/extensions/SecurePoll/cli/wm-scripts/README |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 3 | + native |