Index: trunk/extensions/SecurePoll/SecurePoll.php |
— | — | @@ -95,6 +95,7 @@ |
96 | 96 | 'SecurePoll_SchulzeTallier' => "$dir/includes/talliers/SchulzeTallier.php", |
97 | 97 | 'SecurePoll_AlternativeVoteTallier' => "$dir/includes/talliers/AlternativeVoteTallier.php", |
98 | 98 | 'SecurePoll_Tallier' => "$dir/includes/talliers/Tallier.php", |
| 99 | + 'SecurePoll_CommentDumper' => "$dir/includes/talliers/CommentDumper.php", |
99 | 100 | |
100 | 101 | # user |
101 | 102 | 'SecurePoll_Auth' => "$dir/includes/user/Auth.php", |
Index: trunk/extensions/SecurePoll/includes/talliers/CommentDumper.php |
— | — | @@ -0,0 +1,62 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * A class that dumps the comments from an election |
| 6 | + */ |
| 7 | +class SecurePoll_CommentDumper extends SecurePoll_ElectionTallier { |
| 8 | + var $csvHandle; |
| 9 | + |
| 10 | + function execute() { |
| 11 | + $this->csvHandle = fopen( 'php://temp', 'r+' ); |
| 12 | + return parent::execute(); |
| 13 | + } |
| 14 | + |
| 15 | + /** |
| 16 | + * Add a record. This is the callback function for SecurePoll_Store::callbackValidVotes(). |
| 17 | + * On error, the Status object returned here will be passed through back to |
| 18 | + * the caller of callbackValidVotes(). |
| 19 | + * |
| 20 | + * @param $store SecurePoll_Store |
| 21 | + * @param $record string Encrypted, packed record. |
| 22 | + * @return Status |
| 23 | + */ |
| 24 | + function addRecord( $store, $record ) { |
| 25 | + # Decrypt and unpack |
| 26 | + if ( $this->crypt ) { |
| 27 | + $status = $this->crypt->decrypt( $record ); |
| 28 | + if ( !$status->isOK() ) { |
| 29 | + return $status; |
| 30 | + } |
| 31 | + $record = $status->value; |
| 32 | + } |
| 33 | + $record = rtrim( $record ); |
| 34 | + $scores = $this->ballot->unpackRecord( $record ); |
| 35 | + |
| 36 | + $comments = $scores['comment']; |
| 37 | + unset($scores['comment']); |
| 38 | + $output = array( $comments['native'], $comments['en'] ); |
| 39 | + |
| 40 | + ksort( $output ); |
| 41 | + |
| 42 | + foreach ( $scores as $question ) { |
| 43 | + ksort( $question ); |
| 44 | + $output = array_merge( $output, $question ); |
| 45 | + } |
| 46 | + |
| 47 | + fputcsv( $this->csvHandle, $output ); |
| 48 | + |
| 49 | + return Status::newGood(); |
| 50 | + } |
| 51 | + |
| 52 | + function getHtmlResult() { |
| 53 | + return $this->getTextResult(); |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Get text formatted results for this tally. Should only be called after |
| 58 | + * execute(). |
| 59 | + */ |
| 60 | + function getTextResult() { |
| 61 | + return stream_get_contents( $this->csvHandle, -1, 0 ); |
| 62 | + } |
| 63 | +} |
Index: trunk/extensions/SecurePoll/includes/talliers/HistogramRangeTallier.php |
— | — | @@ -80,7 +80,7 @@ |
81 | 81 | } |
82 | 82 | |
83 | 83 | function getTextResult() { |
84 | | - throw new MWException( __METHOD__.': not yet implemented' ); |
| 84 | + return $this->getHtmlResult(); |
85 | 85 | } |
86 | 86 | } |
87 | 87 | |
Index: trunk/extensions/SecurePoll/cli/dumpComments.php |
— | — | @@ -0,0 +1,69 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Dump the comments from an election from a dump file or local database. |
| 6 | + * |
| 7 | + * For the purposes of the Personal Image Filter referendum, this script |
| 8 | + * dumps the answers to all questions in key order. |
| 9 | + * |
| 10 | + * Can be used to tally very large numbers of votes, when the web interface is |
| 11 | + * not feasible. |
| 12 | + */ |
| 13 | + |
| 14 | +$optionsWithArgs = array( 'name' ); |
| 15 | +require( dirname(__FILE__).'/cli.inc' ); |
| 16 | + |
| 17 | +$wgTitle = Title::newFromText( 'Special:SecurePoll' ); |
| 18 | + |
| 19 | +$usage = <<<EOT |
| 20 | +Usage: |
| 21 | + php dumpComments.php [--html] --name <election name> |
| 22 | + php dumpComments.php [--html] <dump file> |
| 23 | +EOT; |
| 24 | + |
| 25 | +if ( !isset( $options['name'] ) && !isset( $args[0] ) ) { |
| 26 | + spFatal( $usage ); |
| 27 | +} |
| 28 | + |
| 29 | +if ( !class_exists( 'SecurePoll_Context' ) ) { |
| 30 | + if ( isset( $options['name'] ) ) { |
| 31 | + spFatal( "Cannot load from database when SecurePoll is not installed" ); |
| 32 | + } |
| 33 | + require( dirname( __FILE__ ) . '/../SecurePoll.php' ); |
| 34 | +} |
| 35 | + |
| 36 | +$context = new SecurePoll_Context; |
| 37 | +if ( !isset( $options['name'] ) ) { |
| 38 | + $context = SecurePoll_Context::newFromXmlFile( $args[0] ); |
| 39 | + if ( !$context ) { |
| 40 | + spFatal( "Unable to parse XML file \"{$args[0]}\"" ); |
| 41 | + } |
| 42 | + $electionIds = $context->getStore()->getAllElectionIds(); |
| 43 | + if ( !count( $electionIds ) ) { |
| 44 | + spFatal( "No elections found in XML file \"{$args[0]}\"" ); |
| 45 | + } |
| 46 | + $election = $context->getElection( reset( $electionIds ) ); |
| 47 | +} else { |
| 48 | + $election = $context->getElectionByTitle( $options['name'] ); |
| 49 | + if ( !$election ) { |
| 50 | + spFatal( "The specified election does not exist." ); |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +$tallier = new SecurePoll_CommentDumper( $context, $election ); |
| 55 | +$status = $tallier->execute(); |
| 56 | +if ( !$status->isOK() ) { |
| 57 | + spFatal( "Tally error: " . $status->getWikiText() ); |
| 58 | +} |
| 59 | +//$tallier = $status->value; |
| 60 | +if ( isset( $options['html'] ) ) { |
| 61 | + echo $tallier->getHtmlResult(); |
| 62 | +} else { |
| 63 | + echo $tallier->getTextResult(); |
| 64 | +} |
| 65 | + |
| 66 | + |
| 67 | +function spFatal( $message ) { |
| 68 | + fwrite( STDERR, rtrim( $message ) . "\n" ); |
| 69 | + exit( 1 ); |
| 70 | +} |