Index: trunk/extensions/QPoll/i18n/qp.i18n.php |
— | — | @@ -238,7 +238,7 @@ |
239 | 239 | 'qp_error_too_many_spans' => 'There cannot be more category groups defined than the total count of subcategories.', |
240 | 240 | 'qp_error_too_long_category_option_value' => 'Question type="text" categories with more than one text option to chose are displayed as html select/options list. Submitted (chosen) option value is stored in the database field. If the length of chosen value is too long, the value will be partially lost and select/option will not be properly highlighted. That\'s why the length limit is enforced.', |
241 | 241 | 'qp_error_too_long_category_options_values' => 'Question type="text" categories with more than one text option to chose are displayed as html select/options list. Submitted (chosen) options values are stored in the database field. If the total length of chosen values is too long, some of the values will be partially lost and select/options will not be properly highlighted. That\'s why the length limit is enforced.', |
242 | | - 'qp_error_too_long_proposal_text' => "Question type=\"text\" stores it's proposal parts and category definitions in 'proposal_text' field of database table, serialized. If serialized data is longer than database table field length, some of data will be lost and unserialization will be impossible. That's why the length limit is enforced.", |
| 242 | + 'qp_error_too_long_proposal_text' => "Question type=\"text\" stores it's proposal parts and category definitions in 'proposal_text' field of database table, serialized. If serialized data is longer than database table field length, some of data will be lost and unserialization will be impossible. Also, proposal name (which may be used by interpretation script) is stored in the same field, when defined. That's why the length limit is enforced.", |
243 | 243 | 'qp_error_too_few_spans' => 'Every category group should include at least two subcategories', |
244 | 244 | 'qp_error_no_interpretation' => 'Title of interpretation script was specified in poll header, but no article was found with that title. Either remove "interpretation" xml attribute of poll or create the title specified by "interpretation" attribute.', |
245 | 245 | 'qp_error_interpretation_no_return' => 'Interpretation script missed an return statement.', |
Index: trunk/extensions/QPoll/specials/qp_results.php |
— | — | @@ -274,38 +274,38 @@ |
275 | 275 | try { |
276 | 276 | require_once( qp_Setup::$ExtDir . '/Excel/Excel_Writer.php' ); |
277 | 277 | $xls_fname = tempnam( "", ".xls" ); |
278 | | - $xls_workbook = new Spreadsheet_Excel_Writer_Workbook( $xls_fname ); |
279 | | - $xls_workbook->setVersion( 8 ); |
280 | | - $qp_xls = qp_Excel::newFromWorksheet( $xls_workbook->addworksheet() ); |
| 278 | + $qp_xls = new qp_XlsPoll( $xls_fname ); |
281 | 279 | # setup common formats |
282 | | - $format = array( |
283 | | - 'heading' => $xls_workbook->addformat( array( 'bold' => 1 ) ), |
284 | | - 'answer' => $xls_workbook->addformat( array( 'fgcolor' => 0x1A, 'border' => 1 ) ), |
285 | | - 'even' => $xls_workbook->addformat( array( 'fgcolor' => 0x2A, 'border' => 1 ) ), |
286 | | - 'odd' => $xls_workbook->addformat( array( 'fgcolor' => 0x23, 'border' => 1 ) ) |
287 | | - ); |
288 | | - $format['answer']->setAlign( 'left' ); |
289 | | - $format['even']->setAlign( 'left' ); |
290 | | - $format['odd']->setAlign( 'left' ); |
| 280 | + $qp_xls->addFormats( array( |
| 281 | + 'heading' => array( 'bold' => 1 ), |
| 282 | + 'answer' => array( 'fgcolor' => 0x1A /* 26 */, 'border' => 1 ), |
| 283 | + 'even' => array( 'fgcolor' => 0x2A /* 42 */, 'border' => 1 ), |
| 284 | + 'odd' => array( 'fgcolor' => 0x23 /* 35 */, 'border' => 1 ) |
| 285 | + ) ); |
| 286 | + $qp_xls->getFormat( 'answer' )->setAlign( 'left' ); |
| 287 | + $qp_xls->getFormat( 'even' )->setAlign( 'left' ); |
| 288 | + $qp_xls->getFormat( 'odd' )->setAlign( 'left' ); |
291 | 289 | switch ( $cmd ) { |
292 | 290 | case 'voices_xls' : |
293 | | - $qp_xls->voicesToXLS( $format, $pollStore ); |
| 291 | + $qp_xls->voicesToXLS( $pollStore ); |
294 | 292 | break; |
295 | 293 | case 'stats_xls' : |
296 | 294 | # statistics export uses additional formats |
297 | 295 | $percent_num_format = '[Blue]0.0%;[Red]-0.0%;[Black]0%'; |
298 | | - $format['percent'] = $xls_workbook->addformat( array( 'fgcolor' => 0x1A, 'border' => 1 ) ); |
299 | | - $format['percent']->setAlign( 'left' ); |
300 | | - $format['percent']->setNumFormat( $percent_num_format ); |
301 | | - $format['even']->setNumFormat( $percent_num_format ); |
302 | | - $format['odd']->setNumFormat( $percent_num_format ); |
303 | | - $qp_xls->statsToXLS( $format, $pollStore ); |
| 296 | + $qp_xls->addFormats( array( |
| 297 | + 'percent' => array( 'fgcolor' => 0x1A, 'border' => 1 ) |
| 298 | + ) ); |
| 299 | + $qp_xls->getFormat( 'percent' )->setAlign( 'left' ); |
| 300 | + $qp_xls->getFormat( 'percent' )->setNumFormat( $percent_num_format ); |
| 301 | + $qp_xls->getFormat( 'even' )->setNumFormat( $percent_num_format ); |
| 302 | + $qp_xls->getFormat( 'odd' )->setNumFormat( $percent_num_format ); |
| 303 | + $qp_xls->statsToXLS( $pollStore ); |
304 | 304 | break; |
305 | 305 | case 'interpretation_xls' : |
306 | | - $qp_xls->interpretationToXLS( $format, $pollStore ); |
| 306 | + $qp_xls->interpretationToXLS( $pollStore ); |
307 | 307 | break; |
308 | 308 | } |
309 | | - $xls_workbook->close(); |
| 309 | + $qp_xls->closeWorkbook(); |
310 | 310 | header( 'Content-Type: application/x-msexcel; name="' . $poll_id . '.xls"' ); |
311 | 311 | header( 'Content-Disposition: inline; filename="' . $poll_id . '.xls"' ); |
312 | 312 | $fxls = @fopen( $xls_fname, "rb" ); |
Index: trunk/extensions/QPoll/ctrl/question/qp_textquestion.php |
— | — | @@ -468,6 +468,7 @@ |
469 | 469 | # set proposal name (if any) |
470 | 470 | $prop_name = qp_QuestionData::splitRawProposal( $raw ); |
471 | 471 | $this->dbtokens = $brace_stack = array(); |
| 472 | + $dbtokens_idx = -1; |
472 | 473 | $catId = 0; |
473 | 474 | $last_brace = ''; |
474 | 475 | $this->rawtokens = preg_split( $this->propCatPattern, $raw, -1, PREG_SPLIT_DELIM_CAPTURE ); |
— | — | @@ -508,7 +509,7 @@ |
509 | 510 | if ( array_key_exists( 'iscat', $brace_match ) ) { |
510 | 511 | $matching_closed_brace = ''; |
511 | 512 | # add new category input options for the storage |
512 | | - $this->dbtokens[] = $opt->input_options; |
| 513 | + $this->dbtokens[++$dbtokens_idx] = $opt->input_options; |
513 | 514 | # setup mCategories |
514 | 515 | $this->mCategories[$catId] = array( 'name' => strval( $catId ) ); |
515 | 516 | # load proposal/category answer (when available) |
— | — | @@ -524,7 +525,11 @@ |
525 | 526 | $opt->addToLastOption( $token ); |
526 | 527 | } else { |
527 | 528 | # add new proposal part |
528 | | - $this->dbtokens[] = strval( $token ); |
| 529 | + if ( $dbtokens_idx >= 0 && is_string( $this->dbtokens[$dbtokens_idx] ) ) { |
| 530 | + $this->dbtokens[$dbtokens_idx] .= strval( $token ); |
| 531 | + } else { |
| 532 | + $this->dbtokens[++$dbtokens_idx] = strval( $token ); |
| 533 | + } |
529 | 534 | $this->propview->addProposalPart( $token ); |
530 | 535 | } |
531 | 536 | } |
Index: trunk/extensions/QPoll/qp_user.php |
— | — | @@ -329,7 +329,7 @@ |
330 | 330 | 'qp_user.php' => 'qp_Setup', |
331 | 331 | 'includes/qp_functionshook.php' => 'qp_FunctionsHook', |
332 | 332 | 'includes/qp_renderer.php' => 'qp_Renderer', |
333 | | - 'includes/qp_excel.php' => 'qp_Excel', |
| 333 | + 'includes/qp_xlswriter.php' => 'qp_XlsWriter', |
334 | 334 | |
335 | 335 | ## DB schema updater |
336 | 336 | 'maintenance/qp_schemaupdater.php' => 'qp_SchemaUpdater', |
— | — | @@ -371,6 +371,10 @@ |
372 | 372 | ## question data views are used to display question results in Special:PollResults page |
373 | 373 | 'view/results/qp_questiondataresults.php' => 'qp_QuestionDataResults', |
374 | 374 | 'view/results/qp_textquestiondataresults.php' => 'qp_TextQuestionDataResults', |
| 375 | + ## exporting results into XLS format |
| 376 | + 'view/xls/qp_xlspoll.php' => 'qp_XlsPoll', |
| 377 | + 'view/xls/qp_xlstabularquestion.php' => 'qp_XlsTabularQuestion', |
| 378 | + 'view/xls/qp_xlstextquestion.php' => 'qp_XlsTextQuestion', |
375 | 379 | # interpretation results |
376 | 380 | 'view/qp_interpresultview.php' => 'qp_InterpResultView', |
377 | 381 | |
Index: trunk/extensions/QPoll/includes/qp_excel.php |
— | — | @@ -1,278 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * ***** BEGIN LICENSE BLOCK ***** |
5 | | - * This file is part of QPoll. |
6 | | - * Uses parts of code from Quiz extension (c) 2007 Louis-Rémi BABE. All rights reserved. |
7 | | - * |
8 | | - * QPoll is free software; you can redistribute it and/or modify |
9 | | - * it under the terms of the GNU General Public License as published by |
10 | | - * the Free Software Foundation; either version 2 of the License, or |
11 | | - * (at your option) any later version. |
12 | | - * |
13 | | - * QPoll is distributed in the hope that it will be useful, |
14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | - * GNU General Public License for more details. |
17 | | - * |
18 | | - * You should have received a copy of the GNU General Public License |
19 | | - * along with QPoll; if not, write to the Free Software |
20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | | - * |
22 | | - * ***** END LICENSE BLOCK ***** |
23 | | - * |
24 | | - * QPoll is a poll tool for MediaWiki. |
25 | | - * |
26 | | - * To activate this extension : |
27 | | - * * Create a new directory named QPoll into the directory "extensions" of MediaWiki. |
28 | | - * * Place the files from the extension archive there. |
29 | | - * * Add this line at the end of your LocalSettings.php file : |
30 | | - * require_once "$IP/extensions/QPoll/qp_user.php"; |
31 | | - * |
32 | | - * @version 0.8.0a |
33 | | - * @link http://www.mediawiki.org/wiki/Extension:QPoll |
34 | | - * @author QuestPC <questpc@rambler.ru> |
35 | | - */ |
36 | | - |
37 | | -if ( !defined( 'MEDIAWIKI' ) ) { |
38 | | - die( "This file is part of the QPoll extension. It is not a valid entry point.\n" ); |
39 | | -} |
40 | | - |
41 | | -/** |
42 | | - * PEAR Excel helper / wrapper |
43 | | - * |
44 | | - */ |
45 | | -class qp_Excel { |
46 | | - |
47 | | - # an instance of XLS worksheet |
48 | | - var $ws; |
49 | | - # list of formats added to workbook |
50 | | - var $format; |
51 | | - # current row number in a worksheet |
52 | | - var $rownum = 0; |
53 | | - |
54 | | - static function newFromWorksheet( Spreadsheet_Excel_Writer_Worksheet $worksheet ) { |
55 | | - $self = new self(); |
56 | | - $self->ws = $worksheet; |
57 | | - $self->ws->setInputEncoding( "utf-8" ); |
58 | | - $self->ws->setPaper( 9 ); |
59 | | - return $self; |
60 | | - } |
61 | | - |
62 | | - static function prepareExcelString( $s ) { |
63 | | - if ( preg_match( '`^=.?`', $s ) ) { |
64 | | - return "'" . $s; |
65 | | - } |
66 | | - return $s; |
67 | | - } |
68 | | - |
69 | | - function writeFormattedTable( $colnum, &$table, $format = null ) { |
70 | | - $ws = $this->ws; |
71 | | - foreach ( $table as $rnum => &$row ) { |
72 | | - foreach ( $row as $cnum => &$cell ) { |
73 | | - if ( is_array( $cell ) ) { |
74 | | - if ( array_key_exists( "format", $cell ) ) { |
75 | | - $ws->write( $this->rownum + $rnum, $colnum + $cnum, $cell[ 0 ], $cell[ "format" ] ); |
76 | | - } else { |
77 | | - $ws->write( $this->rownum + $rnum, $colnum + $cnum, $cell[ 0 ], $format ); |
78 | | - } |
79 | | - } else { |
80 | | - $ws->write( $this->rownum + $rnum, $colnum + $cnum, $cell, $format ); |
81 | | - } |
82 | | - } |
83 | | - } |
84 | | - } |
85 | | - |
86 | | - function writeHeader( $totalUsersAnsweredQuestion ) { |
87 | | - $this->ws->write( $this->rownum, 0, $totalUsersAnsweredQuestion, $this->format['heading'] ); |
88 | | - $this->ws->write( $this->rownum++, 1, wfMsgExt( 'qp_users_answered_questions', array( 'parsemag' ), $totalUsersAnsweredQuestion ), $this->format['heading'] ); |
89 | | - $this->rownum++; |
90 | | - } |
91 | | - |
92 | | - function voicesToXls( $format, qp_PollStore $pollStore ) { |
93 | | - $this->format = &$format; |
94 | | - $pollStore->loadQuestions(); |
95 | | - $ws = $this->ws; |
96 | | - $first_question = true; |
97 | | - foreach ( $pollStore->Questions as $qkey => &$qdata ) { |
98 | | - if ( $first_question ) { |
99 | | - $this->writeHeader( $pollStore->totalUsersAnsweredQuestion( $qdata ) ); |
100 | | - } else { |
101 | | - # get maximum count of voters of the first question |
102 | | - $total_voters = $first_question_voters; |
103 | | - } |
104 | | - $ws->write( $this->rownum, 0, $qdata->question_id, $format['heading'] ); |
105 | | - $ws->write( $this->rownum++, 1, self::prepareExcelString( $qdata->CommonQuestion ), $format['heading'] ); |
106 | | - if ( count( $qdata->CategorySpans ) > 0 ) { |
107 | | - $row = array(); |
108 | | - foreach ( $qdata->CategorySpans as &$span ) { |
109 | | - $row[] = self::prepareExcelString( $span[ "name" ] ); |
110 | | - for ( $i = 1; $i < $span[ "count" ]; $i++ ) { |
111 | | - $row[] = ""; |
112 | | - } |
113 | | - } |
114 | | - $ws->writerow( $this->rownum++, 0, $row ); |
115 | | - } |
116 | | - $row = array(); |
117 | | - foreach ( $qdata->Categories as &$categ ) { |
118 | | - $row[] = self::prepareExcelString( $categ[ "name" ] ); |
119 | | - } |
120 | | - $ws->writerow( $this->rownum++, 0, $row ); |
121 | | -/* |
122 | | - foreach ( $qdata->Percents as $pkey=>&$percent ) { |
123 | | - $ws->writerow( $this->rownum + $pkey, 0, $percent ); |
124 | | - } |
125 | | -*/ |
126 | | - $voters = array(); |
127 | | - $offset = 0; |
128 | | - $spansUsed = count( $qdata->CategorySpans ) > 0 || $qdata->type == "multipleChoice"; |
129 | | - # iterate through the voters of the current poll (there might be many) |
130 | | - while ( ( $limit = count( $voters = $pollStore->pollVotersPager( $offset ) ) ) > 0 ) { |
131 | | - if ( !$first_question ) { |
132 | | - # do not export more user voices than first question has |
133 | | - for ( $total_voters -= $limit; $total_voters < 0 && $limit > 0; $total_voters++, $limit-- ) { |
134 | | - array_pop( $voters ); |
135 | | - } |
136 | | - if ( count( $voters ) === 0 ) { |
137 | | - break; |
138 | | - } |
139 | | - } |
140 | | - $uvoices = $pollStore->questionVoicesRange( $qdata->question_id, array_keys( $voters ) ); |
141 | | - # get each of proposal votes for current uid |
142 | | - foreach ( $uvoices as $uid => &$pvoices ) { |
143 | | - # output square table of proposal / category answers for each uid in uvoices array |
144 | | - $voicesTable = array(); |
145 | | - foreach ( $qdata->ProposalText as $propkey => &$proposal_text ) { |
146 | | - $row = array_fill( 0, count( $qdata->Categories ), '' ); |
147 | | - if ( isset( $pvoices[$propkey] ) ) { |
148 | | - foreach ( $pvoices[$propkey] as $catkey => $text_answer ) { |
149 | | - $row[$catkey] = self::prepareExcelString( $text_answer ); |
150 | | - } |
151 | | - if ( $spansUsed ) { |
152 | | - foreach ( $row as $catkey => &$cell ) { |
153 | | - $cell = array( 0 => $cell ); |
154 | | - if ( $qdata->type == "multipleChoice" ) { |
155 | | - $cell['format'] = ( ( $catkey & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
156 | | - } else { |
157 | | - $cell['format'] = ( ( $qdata->Categories[ $catkey ][ "spanId" ] & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
158 | | - } |
159 | | - } |
160 | | - } |
161 | | - } |
162 | | - $voicesTable[] = $row; |
163 | | - } |
164 | | - $this->writeFormattedTable( 0, $voicesTable, $format['answer'] ); |
165 | | - $row = array(); |
166 | | - foreach ( $qdata->ProposalText as $ptext ) { |
167 | | - $row[] = self::prepareExcelString( $ptext ); |
168 | | - } |
169 | | - $ws->writecol( $this->rownum, count( $qdata->Categories ), $row ); |
170 | | - $this->rownum += count( $qdata->ProposalText ) + 1; |
171 | | - } |
172 | | - if ( !$first_question && $total_voters < 1 ) { |
173 | | - # break on reaching the count of first question user voices |
174 | | - break; |
175 | | - } |
176 | | - $offset += $limit; |
177 | | - } |
178 | | - if ( $first_question ) { |
179 | | - # store maximum count of voters of the first question |
180 | | - $first_question_voters = $offset; |
181 | | - $first_question = false; |
182 | | - } |
183 | | - } |
184 | | - } |
185 | | - |
186 | | - function statsToXls( $format, qp_PollStore $pollStore ) { |
187 | | - $this->format = &$format; |
188 | | - $pollStore->loadQuestions(); |
189 | | - $pollStore->loadTotals(); |
190 | | - $pollStore->calculateStatistics(); |
191 | | - $ws = $this->ws; |
192 | | - $first_question = true; |
193 | | - foreach ( $pollStore->Questions as $qkey => &$qdata ) { |
194 | | - if ( $first_question ) { |
195 | | - $this->writeHeader( $pollStore->totalUsersAnsweredQuestion( $qdata ) ); |
196 | | - $first_question = false; |
197 | | - } |
198 | | - $ws->write( $this->rownum, 0, $qdata->question_id, $format['heading'] ); |
199 | | - $ws->write( $this->rownum++, 1, self::prepareExcelString( $qdata->CommonQuestion ), $format['heading'] ); |
200 | | - if ( count( $qdata->CategorySpans ) > 0 ) { |
201 | | - $row = array(); |
202 | | - foreach ( $qdata->CategorySpans as &$span ) { |
203 | | - $row[] = self::prepareExcelString( $span[ "name" ] ); |
204 | | - for ( $i = 1; $i < $span[ "count" ]; $i++ ) { |
205 | | - $row[] = ""; |
206 | | - } |
207 | | - } |
208 | | - $ws->writerow( $this->rownum++, 0, $row ); |
209 | | - } |
210 | | - $row = array(); |
211 | | - foreach ( $qdata->Categories as &$categ ) { |
212 | | - $row[] = self::prepareExcelString( $categ[ "name" ] ); |
213 | | - } |
214 | | - $ws->writerow( $this->rownum++, 0, $row ); |
215 | | -/* |
216 | | - foreach ( $qdata->Percents as $pkey=>&$percent ) { |
217 | | - $ws->writerow( $this->rownum + $pkey, 0, $percent ); |
218 | | - } |
219 | | -*/ |
220 | | - $percentsTable = array(); |
221 | | - $spansUsed = count( $qdata->CategorySpans ) > 0 || $qdata->type == "multipleChoice"; |
222 | | - foreach ( $qdata->ProposalText as $propkey => &$proposal_text ) { |
223 | | - if ( isset( $qdata->Percents[ $propkey ] ) ) { |
224 | | - $row = $qdata->Percents[ $propkey ]; |
225 | | - foreach ( $row as $catkey => &$cell ) { |
226 | | - $cell = array( 0 => $cell ); |
227 | | - if ( $spansUsed ) { |
228 | | - if ( $qdata->type == "multipleChoice" ) { |
229 | | - $cell['format'] = ( ( $catkey & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
230 | | - } else { |
231 | | - $cell['format'] = ( ( $qdata->Categories[ $catkey ][ "spanId" ] & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
232 | | - } |
233 | | - } |
234 | | - } |
235 | | - } else { |
236 | | - $row = array_fill( 0, count( $qdata->Categories ), '' ); |
237 | | - } |
238 | | - $percentsTable[] = $row; |
239 | | - } |
240 | | - $this->writeFormattedTable( 0, $percentsTable, $format['percent'] ); |
241 | | - $row = array(); |
242 | | - foreach ( $qdata->ProposalText as $ptext ) { |
243 | | - $row[] = self::prepareExcelString( $ptext ); |
244 | | - } |
245 | | - $ws->writecol( $this->rownum, count( $qdata->Categories ), $row ); |
246 | | - $this->rownum += count( $qdata->ProposalText ) + 1; |
247 | | - } |
248 | | - } |
249 | | - |
250 | | - function interpretationToXLS( $format, qp_PollStore $pollStore ) { |
251 | | - $offset = 0; |
252 | | - $ws = $this->ws; |
253 | | - # iterate through the voters of the current poll (there might be many) |
254 | | - while ( ( $limit = count( $voters = $pollStore->pollVotersPager( $offset ) ) ) > 0 ) { |
255 | | - foreach ( $voters as &$voter ) { |
256 | | - if ( $voter['interpretation']->short != '' ) { |
257 | | - $ws->write( $this->rownum++, 0, self::prepareExcelString( wfMsg( 'qp_results_short_interpretation' ) ), $format['heading'] ); |
258 | | - $ws->write( $this->rownum++, 0, self::prepareExcelString( $voter['interpretation']->short ) ); |
259 | | - } |
260 | | - if ( $voter['interpretation']->structured != '' ) { |
261 | | - $ws->write( $this->rownum++, 0, self::prepareExcelString( wfMsg( 'qp_results_structured_interpretation' ) ), $format['heading'] ); |
262 | | - $strucTable = $voter['interpretation']->getStructuredAnswerTable(); |
263 | | - foreach ( $strucTable as &$line ) { |
264 | | - if ( isset( $line['keys'] ) ) { |
265 | | - # current node is associative array |
266 | | - $ws->writeRow( $this->rownum++, 0, $line['keys'], $format['odd'] ); |
267 | | - $ws->writeRow( $this->rownum++, 0, $line['vals'] ); |
268 | | - } else { |
269 | | - $ws->write( $this->rownum++, 0, $line['vals'] ); |
270 | | - } |
271 | | - } |
272 | | - $this->rownum++; |
273 | | - } |
274 | | - } |
275 | | - $offset += $limit; |
276 | | - } |
277 | | - } |
278 | | - |
279 | | -} /* end of qp_Excel class */ |
Index: trunk/extensions/QPoll/includes/qp_xlswriter.php |
— | — | @@ -0,0 +1,278 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * ***** BEGIN LICENSE BLOCK ***** |
| 5 | + * This file is part of QPoll. |
| 6 | + * Uses parts of code from Quiz extension (c) 2007 Louis-Rémi BABE. All rights reserved. |
| 7 | + * |
| 8 | + * QPoll is free software; you can redistribute it and/or modify |
| 9 | + * it under the terms of the GNU General Public License as published by |
| 10 | + * the Free Software Foundation; either version 2 of the License, or |
| 11 | + * (at your option) any later version. |
| 12 | + * |
| 13 | + * QPoll is distributed in the hope that it will be useful, |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | + * GNU General Public License for more details. |
| 17 | + * |
| 18 | + * You should have received a copy of the GNU General Public License |
| 19 | + * along with QPoll; if not, write to the Free Software |
| 20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | + * |
| 22 | + * ***** END LICENSE BLOCK ***** |
| 23 | + * |
| 24 | + * QPoll is a poll tool for MediaWiki. |
| 25 | + * |
| 26 | + * To activate this extension : |
| 27 | + * * Create a new directory named QPoll into the directory "extensions" of MediaWiki. |
| 28 | + * * Place the files from the extension archive there. |
| 29 | + * * Add this line at the end of your LocalSettings.php file : |
| 30 | + * require_once "$IP/extensions/QPoll/qp_user.php"; |
| 31 | + * |
| 32 | + * @version 0.8.0a |
| 33 | + * @link http://www.mediawiki.org/wiki/Extension:QPoll |
| 34 | + * @author QuestPC <questpc@rambler.ru> |
| 35 | + */ |
| 36 | + |
| 37 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 38 | + die( "This file is part of the QPoll extension. It is not a valid entry point.\n" ); |
| 39 | +} |
| 40 | + |
| 41 | +/** |
| 42 | + * PEAR Excel helper / wrapper |
| 43 | + * |
| 44 | + */ |
| 45 | +class qp_Excel { |
| 46 | + |
| 47 | + # an instance of XLS worksheet |
| 48 | + var $ws; |
| 49 | + # list of formats added to workbook |
| 50 | + var $format; |
| 51 | + # current row number in a worksheet |
| 52 | + var $rownum = 0; |
| 53 | + |
| 54 | + static function newFromWorksheet( Spreadsheet_Excel_Writer_Worksheet $worksheet ) { |
| 55 | + $self = new self(); |
| 56 | + $self->ws = $worksheet; |
| 57 | + $self->ws->setInputEncoding( "utf-8" ); |
| 58 | + $self->ws->setPaper( 9 ); |
| 59 | + return $self; |
| 60 | + } |
| 61 | + |
| 62 | + static function prepareExcelString( $s ) { |
| 63 | + if ( preg_match( '`^=.?`', $s ) ) { |
| 64 | + return "'" . $s; |
| 65 | + } |
| 66 | + return $s; |
| 67 | + } |
| 68 | + |
| 69 | + function writeFormattedTable( $colnum, &$table, $format = null ) { |
| 70 | + $ws = $this->ws; |
| 71 | + foreach ( $table as $rnum => &$row ) { |
| 72 | + foreach ( $row as $cnum => &$cell ) { |
| 73 | + if ( is_array( $cell ) ) { |
| 74 | + if ( array_key_exists( "format", $cell ) ) { |
| 75 | + $ws->write( $this->rownum + $rnum, $colnum + $cnum, $cell[ 0 ], $cell[ "format" ] ); |
| 76 | + } else { |
| 77 | + $ws->write( $this->rownum + $rnum, $colnum + $cnum, $cell[ 0 ], $format ); |
| 78 | + } |
| 79 | + } else { |
| 80 | + $ws->write( $this->rownum + $rnum, $colnum + $cnum, $cell, $format ); |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + function writeHeader( $totalUsersAnsweredQuestion ) { |
| 87 | + $this->ws->write( $this->rownum, 0, $totalUsersAnsweredQuestion, $this->format['heading'] ); |
| 88 | + $this->ws->write( $this->rownum++, 1, wfMsgExt( 'qp_users_answered_questions', array( 'parsemag' ), $totalUsersAnsweredQuestion ), $this->format['heading'] ); |
| 89 | + $this->rownum++; |
| 90 | + } |
| 91 | + |
| 92 | + function voicesToXls( $format, qp_PollStore $pollStore ) { |
| 93 | + $this->format = &$format; |
| 94 | + $pollStore->loadQuestions(); |
| 95 | + $ws = $this->ws; |
| 96 | + $first_question = true; |
| 97 | + foreach ( $pollStore->Questions as $qkey => &$qdata ) { |
| 98 | + if ( $first_question ) { |
| 99 | + $this->writeHeader( $pollStore->totalUsersAnsweredQuestion( $qdata ) ); |
| 100 | + } else { |
| 101 | + # get maximum count of voters of the first question |
| 102 | + $total_voters = $first_question_voters; |
| 103 | + } |
| 104 | + $ws->write( $this->rownum, 0, $qdata->question_id, $format['heading'] ); |
| 105 | + $ws->write( $this->rownum++, 1, self::prepareExcelString( $qdata->CommonQuestion ), $format['heading'] ); |
| 106 | + if ( count( $qdata->CategorySpans ) > 0 ) { |
| 107 | + $row = array(); |
| 108 | + foreach ( $qdata->CategorySpans as &$span ) { |
| 109 | + $row[] = self::prepareExcelString( $span[ "name" ] ); |
| 110 | + for ( $i = 1; $i < $span[ "count" ]; $i++ ) { |
| 111 | + $row[] = ""; |
| 112 | + } |
| 113 | + } |
| 114 | + $ws->writerow( $this->rownum++, 0, $row ); |
| 115 | + } |
| 116 | + $row = array(); |
| 117 | + foreach ( $qdata->Categories as &$categ ) { |
| 118 | + $row[] = self::prepareExcelString( $categ[ "name" ] ); |
| 119 | + } |
| 120 | + $ws->writerow( $this->rownum++, 0, $row ); |
| 121 | +/* |
| 122 | + foreach ( $qdata->Percents as $pkey=>&$percent ) { |
| 123 | + $ws->writerow( $this->rownum + $pkey, 0, $percent ); |
| 124 | + } |
| 125 | +*/ |
| 126 | + $voters = array(); |
| 127 | + $offset = 0; |
| 128 | + $spansUsed = count( $qdata->CategorySpans ) > 0 || $qdata->type == "multipleChoice"; |
| 129 | + # iterate through the voters of the current poll (there might be many) |
| 130 | + while ( ( $limit = count( $voters = $pollStore->pollVotersPager( $offset ) ) ) > 0 ) { |
| 131 | + if ( !$first_question ) { |
| 132 | + # do not export more user voices than first question has |
| 133 | + for ( $total_voters -= $limit; $total_voters < 0 && $limit > 0; $total_voters++, $limit-- ) { |
| 134 | + array_pop( $voters ); |
| 135 | + } |
| 136 | + if ( count( $voters ) === 0 ) { |
| 137 | + break; |
| 138 | + } |
| 139 | + } |
| 140 | + $uvoices = $pollStore->questionVoicesRange( $qdata->question_id, array_keys( $voters ) ); |
| 141 | + # get each of proposal votes for current uid |
| 142 | + foreach ( $uvoices as $uid => &$pvoices ) { |
| 143 | + # output square table of proposal / category answers for each uid in uvoices array |
| 144 | + $voicesTable = array(); |
| 145 | + foreach ( $qdata->ProposalText as $propkey => &$proposal_text ) { |
| 146 | + $row = array_fill( 0, count( $qdata->Categories ), '' ); |
| 147 | + if ( isset( $pvoices[$propkey] ) ) { |
| 148 | + foreach ( $pvoices[$propkey] as $catkey => $text_answer ) { |
| 149 | + $row[$catkey] = self::prepareExcelString( $text_answer ); |
| 150 | + } |
| 151 | + if ( $spansUsed ) { |
| 152 | + foreach ( $row as $catkey => &$cell ) { |
| 153 | + $cell = array( 0 => $cell ); |
| 154 | + if ( $qdata->type == "multipleChoice" ) { |
| 155 | + $cell['format'] = ( ( $catkey & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
| 156 | + } else { |
| 157 | + $cell['format'] = ( ( $qdata->Categories[ $catkey ][ "spanId" ] & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
| 158 | + } |
| 159 | + } |
| 160 | + } |
| 161 | + } |
| 162 | + $voicesTable[] = $row; |
| 163 | + } |
| 164 | + $this->writeFormattedTable( 0, $voicesTable, $format['answer'] ); |
| 165 | + $row = array(); |
| 166 | + foreach ( $qdata->ProposalText as $ptext ) { |
| 167 | + $row[] = self::prepareExcelString( $ptext ); |
| 168 | + } |
| 169 | + $ws->writecol( $this->rownum, count( $qdata->Categories ), $row ); |
| 170 | + $this->rownum += count( $qdata->ProposalText ) + 1; |
| 171 | + } |
| 172 | + if ( !$first_question && $total_voters < 1 ) { |
| 173 | + # break on reaching the count of first question user voices |
| 174 | + break; |
| 175 | + } |
| 176 | + $offset += $limit; |
| 177 | + } |
| 178 | + if ( $first_question ) { |
| 179 | + # store maximum count of voters of the first question |
| 180 | + $first_question_voters = $offset; |
| 181 | + $first_question = false; |
| 182 | + } |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + function statsToXls( $format, qp_PollStore $pollStore ) { |
| 187 | + $this->format = &$format; |
| 188 | + $pollStore->loadQuestions(); |
| 189 | + $pollStore->loadTotals(); |
| 190 | + $pollStore->calculateStatistics(); |
| 191 | + $ws = $this->ws; |
| 192 | + $first_question = true; |
| 193 | + foreach ( $pollStore->Questions as $qkey => &$qdata ) { |
| 194 | + if ( $first_question ) { |
| 195 | + $this->writeHeader( $pollStore->totalUsersAnsweredQuestion( $qdata ) ); |
| 196 | + $first_question = false; |
| 197 | + } |
| 198 | + $ws->write( $this->rownum, 0, $qdata->question_id, $format['heading'] ); |
| 199 | + $ws->write( $this->rownum++, 1, self::prepareExcelString( $qdata->CommonQuestion ), $format['heading'] ); |
| 200 | + if ( count( $qdata->CategorySpans ) > 0 ) { |
| 201 | + $row = array(); |
| 202 | + foreach ( $qdata->CategorySpans as &$span ) { |
| 203 | + $row[] = self::prepareExcelString( $span[ "name" ] ); |
| 204 | + for ( $i = 1; $i < $span[ "count" ]; $i++ ) { |
| 205 | + $row[] = ""; |
| 206 | + } |
| 207 | + } |
| 208 | + $ws->writerow( $this->rownum++, 0, $row ); |
| 209 | + } |
| 210 | + $row = array(); |
| 211 | + foreach ( $qdata->Categories as &$categ ) { |
| 212 | + $row[] = self::prepareExcelString( $categ[ "name" ] ); |
| 213 | + } |
| 214 | + $ws->writerow( $this->rownum++, 0, $row ); |
| 215 | +/* |
| 216 | + foreach ( $qdata->Percents as $pkey=>&$percent ) { |
| 217 | + $ws->writerow( $this->rownum + $pkey, 0, $percent ); |
| 218 | + } |
| 219 | +*/ |
| 220 | + $percentsTable = array(); |
| 221 | + $spansUsed = count( $qdata->CategorySpans ) > 0 || $qdata->type == "multipleChoice"; |
| 222 | + foreach ( $qdata->ProposalText as $propkey => &$proposal_text ) { |
| 223 | + if ( isset( $qdata->Percents[ $propkey ] ) ) { |
| 224 | + $row = $qdata->Percents[ $propkey ]; |
| 225 | + foreach ( $row as $catkey => &$cell ) { |
| 226 | + $cell = array( 0 => $cell ); |
| 227 | + if ( $spansUsed ) { |
| 228 | + if ( $qdata->type == "multipleChoice" ) { |
| 229 | + $cell['format'] = ( ( $catkey & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
| 230 | + } else { |
| 231 | + $cell['format'] = ( ( $qdata->Categories[ $catkey ][ "spanId" ] & 1 ) === 0 ) ? $format['even'] : $format['odd']; |
| 232 | + } |
| 233 | + } |
| 234 | + } |
| 235 | + } else { |
| 236 | + $row = array_fill( 0, count( $qdata->Categories ), '' ); |
| 237 | + } |
| 238 | + $percentsTable[] = $row; |
| 239 | + } |
| 240 | + $this->writeFormattedTable( 0, $percentsTable, $format['percent'] ); |
| 241 | + $row = array(); |
| 242 | + foreach ( $qdata->ProposalText as $ptext ) { |
| 243 | + $row[] = self::prepareExcelString( $ptext ); |
| 244 | + } |
| 245 | + $ws->writecol( $this->rownum, count( $qdata->Categories ), $row ); |
| 246 | + $this->rownum += count( $qdata->ProposalText ) + 1; |
| 247 | + } |
| 248 | + } |
| 249 | + |
| 250 | + function interpretationToXLS( $format, qp_PollStore $pollStore ) { |
| 251 | + $offset = 0; |
| 252 | + $ws = $this->ws; |
| 253 | + # iterate through the voters of the current poll (there might be many) |
| 254 | + while ( ( $limit = count( $voters = $pollStore->pollVotersPager( $offset ) ) ) > 0 ) { |
| 255 | + foreach ( $voters as &$voter ) { |
| 256 | + if ( $voter['interpretation']->short != '' ) { |
| 257 | + $ws->write( $this->rownum++, 0, self::prepareExcelString( wfMsg( 'qp_results_short_interpretation' ) ), $format['heading'] ); |
| 258 | + $ws->write( $this->rownum++, 0, self::prepareExcelString( $voter['interpretation']->short ) ); |
| 259 | + } |
| 260 | + if ( $voter['interpretation']->structured != '' ) { |
| 261 | + $ws->write( $this->rownum++, 0, self::prepareExcelString( wfMsg( 'qp_results_structured_interpretation' ) ), $format['heading'] ); |
| 262 | + $strucTable = $voter['interpretation']->getStructuredAnswerTable(); |
| 263 | + foreach ( $strucTable as &$line ) { |
| 264 | + if ( isset( $line['keys'] ) ) { |
| 265 | + # current node is associative array |
| 266 | + $ws->writeRow( $this->rownum++, 0, $line['keys'], $format['odd'] ); |
| 267 | + $ws->writeRow( $this->rownum++, 0, $line['vals'] ); |
| 268 | + } else { |
| 269 | + $ws->write( $this->rownum++, 0, $line['vals'] ); |
| 270 | + } |
| 271 | + } |
| 272 | + $this->rownum++; |
| 273 | + } |
| 274 | + } |
| 275 | + $offset += $limit; |
| 276 | + } |
| 277 | + } |
| 278 | + |
| 279 | +} /* end of qp_Excel class */ |
Property changes on: trunk/extensions/QPoll/includes/qp_xlswriter.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 280 | + native |
Index: trunk/extensions/QPoll/view/xls/qp_xlstabularquestion.php |
— | — | @@ -0,0 +1,95 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class qp_XlsTabularQuestion extends qp_XlsWriter { |
| 5 | + |
| 6 | + var $qdata; |
| 7 | + |
| 8 | + var $spansUsed; |
| 9 | + |
| 10 | + function setQuestionData( qp_QuestionData $qdata ) { |
| 11 | + $this->qdata = $qdata; |
| 12 | + $this->spansUsed = count( $qdata->CategorySpans ) > 0 || $qdata->type == 'multipleChoice'; |
| 13 | + } |
| 14 | + |
| 15 | + function writeHeader() { |
| 16 | + $this->write( 0, $this->qdata->question_id, 'heading' ); |
| 17 | + $this->writeLn( 1, $this->qdata->CommonQuestion, 'heading' ); |
| 18 | + if ( count( $this->qdata->CategorySpans ) > 0 ) { |
| 19 | + $row = array(); |
| 20 | + foreach ( $this->qdata->CategorySpans as &$span ) { |
| 21 | + $row[] = $span['name']; |
| 22 | + for ( $i = 1; $i < $span['count']; $i++ ) { |
| 23 | + $row[] = ''; |
| 24 | + } |
| 25 | + } |
| 26 | + $this->writeRowLn( 0, $row ); |
| 27 | + } |
| 28 | + $row = array(); |
| 29 | + foreach ( $this->qdata->Categories as &$categ ) { |
| 30 | + $row[] = $categ['name']; |
| 31 | + } |
| 32 | + $this->writeRowLn( 0, $row ); |
| 33 | + } |
| 34 | + |
| 35 | + function writeQuestionVoice( $pvoices ) { |
| 36 | + $qdata = $this->qdata; |
| 37 | + # create square table of proposal / category answers for each uid in uvoices array |
| 38 | + $voicesTable = array(); |
| 39 | + foreach ( $qdata->ProposalText as $propkey => &$proposal_text ) { |
| 40 | + $row = array_fill( 0, count( $qdata->Categories ), '' ); |
| 41 | + if ( isset( $pvoices[$propkey] ) ) { |
| 42 | + foreach ( $pvoices[$propkey] as $catkey => $text_answer ) { |
| 43 | + $row[$catkey] = $text_answer; |
| 44 | + } |
| 45 | + if ( $this->spansUsed ) { |
| 46 | + foreach ( $row as $catkey => &$cell ) { |
| 47 | + $cell = array( 0 => $cell ); |
| 48 | + if ( $qdata->type == 'multipleChoice' ) { |
| 49 | + $cell['format'] = ( ( $catkey & 1 ) === 0 ) ? 'even' : 'odd'; |
| 50 | + } else { |
| 51 | + $cell['format'] = ( ( $qdata->Categories[ $catkey ][ "spanId" ] & 1 ) === 0 ) ? 'even' : 'odd'; |
| 52 | + } |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + $voicesTable[] = $row; |
| 57 | + } |
| 58 | + $this->writeFormattedTable( 0, $voicesTable, 'answer' ); |
| 59 | + $row = array(); |
| 60 | + foreach ( $qdata->ProposalText as $ptext ) { |
| 61 | + $row[] = $ptext; |
| 62 | + } |
| 63 | + $this->writeCol( count( $qdata->Categories ), $row ); |
| 64 | + $this->relRow( count( $qdata->ProposalText ) + 1 ); |
| 65 | + } |
| 66 | + |
| 67 | + function writeQuestionStats() { |
| 68 | + $qdata = $this->qdata; |
| 69 | + foreach ( $qdata->ProposalText as $propkey => &$proposal_text ) { |
| 70 | + if ( isset( $qdata->Percents[ $propkey ] ) ) { |
| 71 | + $row = $qdata->Percents[ $propkey ]; |
| 72 | + foreach ( $row as $catkey => &$cell ) { |
| 73 | + $cell = array( 0 => $cell ); |
| 74 | + if ( $this->spansUsed ) { |
| 75 | + if ( $qdata->type == 'multipleChoice' ) { |
| 76 | + $cell['format'] = ( ( $catkey & 1 ) === 0 ) ? 'even' : 'odd'; |
| 77 | + } else { |
| 78 | + $cell['format'] = ( ( $qdata->Categories[ $catkey ][ "spanId" ] & 1 ) === 0 ) ? 'even' : 'odd'; |
| 79 | + } |
| 80 | + } |
| 81 | + } |
| 82 | + } else { |
| 83 | + $row = array_fill( 0, count( $qdata->Categories ), '' ); |
| 84 | + } |
| 85 | + $percentsTable[] = $row; |
| 86 | + } |
| 87 | + $this->writeFormattedTable( 0, $percentsTable, 'percent' ); |
| 88 | + $row = array(); |
| 89 | + foreach ( $qdata->ProposalText as $ptext ) { |
| 90 | + $row[] = $ptext; |
| 91 | + } |
| 92 | + $this->writeCol( count( $qdata->Categories ), $row ); |
| 93 | + $this->relRow( count( $qdata->ProposalText ) + 1 ); |
| 94 | + } |
| 95 | + |
| 96 | +} /* end of qp_XlsTabularQuestion class */ |
Property changes on: trunk/extensions/QPoll/view/xls/qp_xlstabularquestion.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 97 | + native |
Index: trunk/extensions/QPoll/view/xls/qp_xlspoll.php |
— | — | @@ -0,0 +1,160 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * ***** BEGIN LICENSE BLOCK ***** |
| 5 | + * This file is part of QPoll. |
| 6 | + * Uses parts of code from Quiz extension (c) 2007 Louis-Rémi BABE. All rights reserved. |
| 7 | + * |
| 8 | + * QPoll is free software; you can redistribute it and/or modify |
| 9 | + * it under the terms of the GNU General Public License as published by |
| 10 | + * the Free Software Foundation; either version 2 of the License, or |
| 11 | + * (at your option) any later version. |
| 12 | + * |
| 13 | + * QPoll is distributed in the hope that it will be useful, |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | + * GNU General Public License for more details. |
| 17 | + * |
| 18 | + * You should have received a copy of the GNU General Public License |
| 19 | + * along with QPoll; if not, write to the Free Software |
| 20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | + * |
| 22 | + * ***** END LICENSE BLOCK ***** |
| 23 | + * |
| 24 | + * QPoll is a poll tool for MediaWiki. |
| 25 | + * |
| 26 | + * To activate this extension : |
| 27 | + * * Create a new directory named QPoll into the directory "extensions" of MediaWiki. |
| 28 | + * * Place the files from the extension archive there. |
| 29 | + * * Add this line at the end of your LocalSettings.php file : |
| 30 | + * require_once "$IP/extensions/QPoll/qp_user.php"; |
| 31 | + * |
| 32 | + * @version 0.8.0a |
| 33 | + * @link http://www.mediawiki.org/wiki/Extension:QPoll |
| 34 | + * @author QuestPC <questpc@rambler.ru> |
| 35 | + */ |
| 36 | + |
| 37 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 38 | + die( "This file is part of the QPoll extension. It is not a valid entry point.\n" ); |
| 39 | +} |
| 40 | + |
| 41 | +/** |
| 42 | + * PEAR Excel helper / wrapper |
| 43 | + * |
| 44 | + */ |
| 45 | +class qp_XlsPoll extends qp_XlsWriter { |
| 46 | + |
| 47 | + var $tabular_writer; |
| 48 | + var $text_writer; |
| 49 | + |
| 50 | + function __construct( $xls_fname = null ) { |
| 51 | + parent::__construct( $xls_fname ); |
| 52 | + # Create question writers; Single instances will be re-used in the top loop. |
| 53 | + # They are sharing the same instance of Spreadsheet_Excel_Writer_Worksheet. |
| 54 | + # We do not use class with static properties and methods only because |
| 55 | + # such class names cannot be accessed by reference in PHP < 5.3.0: |
| 56 | + # http://php.net/manual/en/language.oop5.static.php |
| 57 | + # "As of PHP 5.3.0, it's possible to reference the class using a variable. |
| 58 | + # The variable's value can not be a keyword (e.g. self, parent and static)." |
| 59 | + $this->tabular_writer = new qp_XlsTabularQuestion(); |
| 60 | + $this->text_writer = new qp_XlsTextQuestion(); |
| 61 | + } |
| 62 | + |
| 63 | + function writeHeader( $totalUsersAnsweredQuestion ) { |
| 64 | + $this->write( 0, $totalUsersAnsweredQuestion, 'heading' ); |
| 65 | + $this->writeLn( 1, wfMsgExt( 'qp_users_answered_questions', array( 'parsemag' ), $totalUsersAnsweredQuestion ), 'heading' ); |
| 66 | + $this->nextRow(); |
| 67 | + } |
| 68 | + |
| 69 | + function voicesToXls( qp_PollStore $pollStore ) { |
| 70 | + $pollStore->loadQuestions(); |
| 71 | + $first_question = true; |
| 72 | + foreach ( $pollStore->Questions as $qkey => &$qdata ) { |
| 73 | + $xlsq = ( $qdata->type === 'textQuestion' ) ? $this->text_writer : $this->tabular_writer; |
| 74 | + $xlsq->setQuestionData( $qdata ); |
| 75 | + if ( $first_question ) { |
| 76 | + $this->writeHeader( $pollStore->totalUsersAnsweredQuestion( $qdata ) ); |
| 77 | + } else { |
| 78 | + # get maximum count of voters of the first question |
| 79 | + $total_voters = $first_question_voters; |
| 80 | + } |
| 81 | + $xlsq->writeHeader(); |
| 82 | + $voters = array(); |
| 83 | + $offset = 0; |
| 84 | + # iterate through the voters of the current poll (there might be many) |
| 85 | + while ( ( $limit = count( $voters = $pollStore->pollVotersPager( $offset ) ) ) > 0 ) { |
| 86 | + if ( !$first_question ) { |
| 87 | + # do not export more user voices than first question has |
| 88 | + for ( $total_voters -= $limit; $total_voters < 0 && $limit > 0; $total_voters++, $limit-- ) { |
| 89 | + array_pop( $voters ); |
| 90 | + } |
| 91 | + if ( count( $voters ) === 0 ) { |
| 92 | + break; |
| 93 | + } |
| 94 | + } |
| 95 | + $uvoices = $pollStore->questionVoicesRange( $qdata->question_id, array_keys( $voters ) ); |
| 96 | + # get each of proposal votes for current uid |
| 97 | + foreach ( $uvoices as $uid => &$pvoices ) { |
| 98 | + $xlsq->writeQuestionVoice( $pvoices ); |
| 99 | + } |
| 100 | + if ( !$first_question && $total_voters < 1 ) { |
| 101 | + # break on reaching the count of first question user voices |
| 102 | + break; |
| 103 | + } |
| 104 | + $offset += $limit; |
| 105 | + } |
| 106 | + if ( $first_question ) { |
| 107 | + # store maximum count of voters of the first question |
| 108 | + $first_question_voters = $offset; |
| 109 | + $first_question = false; |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + function statsToXls( qp_PollStore $pollStore ) { |
| 115 | + $pollStore->loadQuestions(); |
| 116 | + $pollStore->loadTotals(); |
| 117 | + $pollStore->calculateStatistics(); |
| 118 | + $first_question = true; |
| 119 | + foreach ( $pollStore->Questions as $qkey => &$qdata ) { |
| 120 | + $xlsq = ( $qdata->type === 'textQuestion' ) ? $this->text_writer : $this->tabular_writer; |
| 121 | + $xlsq->setQuestionData( $qdata ); |
| 122 | + if ( $first_question ) { |
| 123 | + $this->writeHeader( $pollStore->totalUsersAnsweredQuestion( $qdata ) ); |
| 124 | + $first_question = false; |
| 125 | + } |
| 126 | + $xlsq->writeHeader(); |
| 127 | + $percentsTable = array(); |
| 128 | + $spansUsed = count( $qdata->CategorySpans ) > 0 || $qdata->type == "multipleChoice"; |
| 129 | + $xlsq->writeQuestionStats(); |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + function interpretationToXLS( qp_PollStore $pollStore ) { |
| 134 | + $offset = 0; |
| 135 | + # iterate through the voters of the current poll (there might be many) |
| 136 | + while ( ( $limit = count( $voters = $pollStore->pollVotersPager( $offset ) ) ) > 0 ) { |
| 137 | + foreach ( $voters as &$voter ) { |
| 138 | + if ( $voter['interpretation']->short != '' ) { |
| 139 | + $this->writeLn( 0, wfMsg( 'qp_results_short_interpretation' ), 'heading' ); |
| 140 | + $this->writeLn( 0, $voter['interpretation']->short ); |
| 141 | + } |
| 142 | + if ( $voter['interpretation']->structured != '' ) { |
| 143 | + $this->writeLn( 0, wfMsg( 'qp_results_structured_interpretation' ), 'heading' ); |
| 144 | + $strucTable = $voter['interpretation']->getStructuredAnswerTable(); |
| 145 | + foreach ( $strucTable as &$line ) { |
| 146 | + if ( isset( $line['keys'] ) ) { |
| 147 | + # current node is associative array |
| 148 | + $this->writeRowLn( 0, $line['keys'], 'odd' ); |
| 149 | + $ws->writeRowLn( 0, $line['vals'] ); |
| 150 | + } else { |
| 151 | + $this->writeLn( 0, $line['vals'] ); |
| 152 | + } |
| 153 | + } |
| 154 | + $this->nextRow(); |
| 155 | + } |
| 156 | + } |
| 157 | + $offset += $limit; |
| 158 | + } |
| 159 | + } |
| 160 | + |
| 161 | +} /* end of qp_XlsPoll class */ |
Property changes on: trunk/extensions/QPoll/view/xls/qp_xlspoll.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 162 | + native |
Index: trunk/extensions/QPoll/view/xls/qp_xlstextquestion.php |
— | — | @@ -0,0 +1,78 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class qp_XlsTextQuestion extends qp_XlsTabularQuestion { |
| 5 | + |
| 6 | + function __construct( $xls_fname = null ) { |
| 7 | + parent::__construct( $xls_fname ); |
| 8 | + $this->addFormats( array( |
| 9 | + 'cat_part' => array( 'fgcolor' => 36, 'border' => 1 ), |
| 10 | + 'prop_part' => array( 'fgcolor' => 34, 'border' => 1 ), |
| 11 | + ) ); |
| 12 | + } |
| 13 | + |
| 14 | + function writeQuestionVoice( $pvoices ) { |
| 15 | + $qdata = $this->qdata; |
| 16 | + foreach ( $qdata->ProposalText as $propkey => &$serialized_tokens ) { |
| 17 | + # Create 2D-table of proposal / category answers for each uid in uvoices array |
| 18 | + # please note that for text question array may be sparce (not rectangular) |
| 19 | + $voicesTable = array(); |
| 20 | + # voicesTable row number |
| 21 | + $rowNum = 0; |
| 22 | + if ( !is_array( $dbtokens = unserialize( $serialized_tokens ) ) ) { |
| 23 | + throw new MWException( 'dbtokens is not an array in ' . __METHOD__ ); |
| 24 | + } |
| 25 | + $catId = 0; |
| 26 | + if ( ( $hasVoices = isset( $pvoices[$propkey] ) ) ) { |
| 27 | + $pv = &$pvoices[$propkey]; |
| 28 | + } |
| 29 | + $voicesTable[$rowNum] = array(); |
| 30 | + # voicesTable column number |
| 31 | + $rowCol = 0; |
| 32 | + # height of current proposal row (may be greater than 1 when more than one text option was selected by user) |
| 33 | + $rowHeight = 1; |
| 34 | + foreach ( $dbtokens as &$token ) { |
| 35 | + if ( is_string( $token ) ) { |
| 36 | + # add a proposal part |
| 37 | + $voicesTable[$rowNum][$rowCol++] = array( $token, 'format' => 'prop_part' ); |
| 38 | + } elseif ( is_array( $token ) ) { |
| 39 | + # add a category definition with selected text answer (if any) |
| 40 | + if ( $hasVoices && isset( $pv[$catId] ) ) { |
| 41 | + if ( $pv[$catId] !== '' ) { |
| 42 | + # text answer |
| 43 | + $selected_options = explode( qp_Setup::SELECT_MULTIPLE_VALUES_SEPARATOR, $pv[$catId] ); |
| 44 | + if ( count( $selected_options ) > 1 ) { |
| 45 | + $saveRowNum = $rowNum; |
| 46 | + foreach ( $selected_options as $option ) { |
| 47 | + if ( !array_key_exists( $rowNum, $voicesTable ) ) { |
| 48 | + $voicesTable[$rowNum] = array(); |
| 49 | + } |
| 50 | + $voicesTable[$rowNum++][$rowCol] = array( $option, 'format' => 'cat_part' ); |
| 51 | + } |
| 52 | + $rowCol++; |
| 53 | + if ( ( $rowNum - $saveRowNum ) > $rowHeight ) { |
| 54 | + $rowHeight = $rowNum - $saveRowNum; |
| 55 | + } |
| 56 | + $rowNum = $saveRowNum; |
| 57 | + } else { |
| 58 | + $voicesTable[$rowNum][$rowCol++] = array( array_pop( $selected_options ), 'format' => 'cat_part' ); |
| 59 | + } |
| 60 | + } else { |
| 61 | + # checkbox or radiobutton |
| 62 | + $voicesTable[$rowNum][$rowCol++] = array( qp_Setup::RESULTS_CHECK_SIGN, 'format' => 'cat_part' ); |
| 63 | + } |
| 64 | + } else { |
| 65 | + # non-selected category (it has no selected option) |
| 66 | + $voicesTable[$rowNum][$rowCol++] = array( '', 'format' => 'cat_part' ); |
| 67 | + } |
| 68 | + $catId++; |
| 69 | + } else { |
| 70 | + throw new MWException( 'DB token has invalid type (' . gettype( $token ) . ') in ' . __METHOD__ ); |
| 71 | + } |
| 72 | + } |
| 73 | + $this->writeFormattedTable( 0, $voicesTable ); |
| 74 | + $this->relRow( $rowHeight ); |
| 75 | + } |
| 76 | + $this->nextRow(); |
| 77 | + } |
| 78 | + |
| 79 | +} /* end of qp_XlsTextQuestion class */ |
Property changes on: trunk/extensions/QPoll/view/xls/qp_xlstextquestion.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 80 | + native |