@@ -132,6 +132,14 @@ public function insert_response($responsedata) {
132
132
$ record ->choice_id = $ answer ->choiceid ;
133
133
$ record ->rankvalue = $ answer ->value ;
134
134
$ resid = $ DB ->insert_record (static ::response_table (), $ record );
135
+ if (isset ($ responsedata ->{$ answer ->choiceid . '_qother ' })) {
136
+ $ otherrecord = new \stdClass ();
137
+ $ otherrecord ->response_id = $ response ->id ;
138
+ $ otherrecord ->question_id = $ this ->question ->id ;
139
+ $ otherrecord ->choice_id = $ answer ->choiceid ;
140
+ $ otherrecord ->response = $ responsedata ->{$ answer ->choiceid . '_qother ' };
141
+ $ DB ->insert_record ('questionnaire_response_other ' , $ otherrecord );
142
+ }
135
143
}
136
144
}
137
145
return $ resid ;
@@ -148,18 +156,29 @@ public function get_results($rids=false, $anonymous=false) {
148
156
global $ DB ;
149
157
150
158
$ rsql = '' ;
159
+ $ params = [];
151
160
if (!empty ($ rids )) {
152
161
list ($ rsql , $ params ) = $ DB ->get_in_or_equal ($ rids );
153
162
$ rsql = ' AND response_id ' . $ rsql ;
154
163
}
164
+ // Get other choices.
165
+ $ otherrecs = $ this ->get_other_choice ($ rsql , $ params );
155
166
156
- $ select = 'question_id= ' . $ this ->question ->id . ' AND content NOT LIKE \' !other% \' ORDER BY id ASC ' ;
167
+ $ select = 'question_id= ' . $ this ->question ->id . ' ORDER BY id ASC ' ;
157
168
if ($ rows = $ DB ->get_records_select ('questionnaire_quest_choice ' , $ select )) {
158
169
foreach ($ rows as $ row ) {
159
- $ this ->counts [$ row ->content ] = new \stdClass ();
160
170
$ nbna = $ DB ->count_records (static ::response_table (), array ('question_id ' => $ this ->question ->id ,
161
- 'choice_id ' => $ row ->id , 'rankvalue ' => '-1 ' ));
162
- $ this ->counts [$ row ->content ]->nbna = $ nbna ;
171
+ 'choice_id ' => $ row ->id , 'rankvalue ' => '-1 ' ));
172
+ if (\mod_questionnaire \question \choice::content_is_other_choice ($ row ->content ) && !empty ($ otherrecs )) {
173
+ foreach (array_keys ($ otherrecs ) as $ key ) {
174
+ $ this ->counts [$ key ] = new \stdClass ();
175
+ $ this ->counts [$ key ]->nbna = $ nbna ;
176
+ $ this ->counts [$ key ]->content = $ row ->content ;
177
+ }
178
+ } else {
179
+ $ this ->counts [$ row ->content ] = new \stdClass ();
180
+ $ this ->counts [$ row ->content ]->nbna = $ nbna ;
181
+ }
163
182
}
164
183
}
165
184
@@ -193,14 +212,30 @@ public function get_results($rids=false, $anonymous=false) {
193
212
}
194
213
195
214
$ sql = "SELECT c.id, c.content, a.average, a.num
196
- FROM {questionnaire_quest_choice} c
197
- INNER JOIN
215
+ FROM {questionnaire_quest_choice} c
216
+ INNER JOIN
198
217
(SELECT c2.id, AVG(a2.rankvalue) AS average, COUNT(a2.response_id) AS num
199
- FROM {questionnaire_quest_choice} c2, { " .static ::response_table ()."} a2
200
- WHERE c2.question_id = ? AND a2.question_id = ? AND a2.choice_id = c2.id AND a2.rankvalue >= 0 {$ rsql }
201
- GROUP BY c2.id) a ON a.id = c.id
202
- order by c.id " ;
218
+ FROM {questionnaire_quest_choice} c2, { " .static ::response_table ()."} a2
219
+ WHERE c2.question_id = ? AND a2.question_id = ? AND a2.choice_id = c2.id
220
+ AND a2.rankvalue >= 0 AND c2.content NOT LIKE '!other%' {$ rsql }
221
+ GROUP BY c2.id) a ON a.id = c.id
222
+ ORDER BY c.id " ;
203
223
$ results = $ DB ->get_records_sql ($ sql , array_merge (array ($ this ->question ->id , $ this ->question ->id ), $ params ));
224
+
225
+ // Handle 'other...'.
226
+ if ($ otherrecs ) {
227
+ $ i = 1 ;
228
+ foreach ($ otherrecs as $ rec ) {
229
+ $ results ['other ' .$ i ] = new \stdClass ();
230
+ $ results ['other ' .$ i ]->id = $ rec ->cid ;
231
+ $ results ['other ' .$ i ]->content = $ rec ->response ;
232
+ $ results ['other ' .$ i ]->average = $ rec ->average ;
233
+ $ results ['other ' .$ i ]->num = $ rec ->num ;
234
+ $ results ['other ' .$ i ]->isother = true ;
235
+ $ i ++;
236
+ }
237
+ }
238
+
204
239
if (!empty ($ rankvalue )) {
205
240
foreach ($ results as $ key => $ result ) {
206
241
if (isset ($ value [$ key ])) {
@@ -217,24 +252,68 @@ public function get_results($rids=false, $anonymous=false) {
217
252
// Case where scaleitems is less than possible choices.
218
253
} else {
219
254
$ sql = "SELECT c.id, c.content, a.sum, a.num
220
- FROM {questionnaire_quest_choice} c
221
- INNER JOIN
255
+ FROM {questionnaire_quest_choice} c
256
+ INNER JOIN
222
257
(SELECT c2.id, SUM(a2.rankvalue) AS sum, COUNT(a2.response_id) AS num
223
- FROM {questionnaire_quest_choice} c2, { " .static ::response_table ()."} a2
224
- WHERE c2.question_id = ? AND a2.question_id = ? AND a2.choice_id = c2.id AND a2.rankvalue >= 0 {$ rsql }
225
- GROUP BY c2.id) a ON a.id = c.id " ;
258
+ FROM {questionnaire_quest_choice} c2, { " .static ::response_table ()."} a2
259
+ WHERE c2.question_id = ? AND a2.question_id = ? AND a2.choice_id = c2.id
260
+ AND a2.rankvalue >= 0 AND c2.content NOT LIKE '!other%' {$ rsql }
261
+ GROUP BY c2.id) a ON a.id = c.id " ;
262
+
226
263
$ results = $ DB ->get_records_sql ($ sql , array_merge (array ($ this ->question ->id , $ this ->question ->id ), $ params ));
264
+
265
+ if ($ otherrecs ) {
266
+ $ i = 1 ;
267
+ foreach ($ otherrecs as $ rec ) {
268
+ $ results ['other ' .$ i ] = new \stdClass ();
269
+ $ results ['other ' .$ i ]->id = $ rec ->cid ;
270
+ $ results ['other ' .$ i ]->content = $ rec ->response ;
271
+ $ results ['other ' .$ i ]->sum = $ rec ->average ;
272
+ $ results ['other ' .$ i ]->num = $ rec ->num ;
273
+ $ results ['other ' .$ i ]->isother = true ;
274
+ $ i ++;
275
+ }
276
+ }
227
277
// Formula to calculate the best ranking order.
228
278
$ nbresponses = count ($ rids );
229
279
foreach ($ results as $ key => $ result ) {
230
- $ result ->average = ($ result ->sum + ($ nbresponses - $ result ->num ) * ($ this ->length + 1 )) / $ nbresponses ;
280
+ if (isset ($ this ->length )) {
281
+ $ result ->average = ($ result ->sum + ($ nbresponses - $ result ->num ) * ($ this ->length + 1 )) / $ nbresponses ;
282
+ } else {
283
+ $ result ->average = ($ result ->sum + ($ nbresponses - $ result ->num ) * 1 ) / $ nbresponses ;
284
+ }
231
285
$ results [$ result ->content ] = $ result ;
232
286
unset($ results [$ key ]);
233
287
}
234
288
return $ results ;
235
289
}
236
290
}
237
291
292
+ /**
293
+ * Get a list of other available choices.
294
+ *
295
+ * @param string $rsql
296
+ * @param array $params
297
+ * @return array
298
+ */
299
+ public function get_other_choice (string $ rsql , array $ params ): array {
300
+ global $ DB ;
301
+ $ osql = "SELECT ro.response, AVG(a.rankvalue) AS average, COUNT(a.response_id) AS num, c.id as cid
302
+ FROM {questionnaire_quest_choice} c
303
+ INNER JOIN { " . static ::response_table () . "} a ON a.choice_id = c.id
304
+ AND a.rankvalue >= 0
305
+ AND a.question_id = c.question_id {$ rsql }
306
+ INNER JOIN {questionnaire_response_other} ro ON ro.choice_id = c.id
307
+ AND ro.response_id = a.response_id
308
+ AND ro.question_id = c.question_id
309
+ WHERE c.question_id = ?
310
+ AND c.content = '!other'
311
+ AND ro.response <> ''
312
+ GROUP BY ro.response, cid
313
+ ORDER BY cid " ;
314
+ return $ DB ->get_records_sql ($ osql , array_merge ($ params , [$ this ->question ->id ]));
315
+ }
316
+
238
317
/**
239
318
* Provide the feedback scores for all requested response id's. This should be provided only by questions that provide feedback.
240
319
* @param array $rids
@@ -417,9 +496,17 @@ public static function response_answers_by_question($rid) {
417
496
global $ DB ;
418
497
419
498
$ answers = [];
420
- $ sql = 'SELECT id, response_id as responseid, question_id as questionid, choice_id as choiceid, rankvalue as value ' .
421
- 'FROM { ' . static ::response_table () .'} ' .
422
- 'WHERE response_id = ? ' ;
499
+ $ sql = 'SELECT r.id,
500
+ r.response_id AS responseid,
501
+ r.question_id AS questionid,
502
+ r.choice_id AS choiceid,
503
+ r.rankvalue AS value,
504
+ rt.response AS otheresponse
505
+ FROM { ' . static ::response_table () . '} r
506
+ LEFT JOIN {questionnaire_response_other} rt ON rt.choice_id = r.choice_id
507
+ AND r.question_id = rt.question_id
508
+ AND r.response_id = rt.response_id
509
+ WHERE r.response_id = ? ' ;
423
510
$ records = $ DB ->get_records_sql ($ sql , [$ rid ]);
424
511
foreach ($ records as $ record ) {
425
512
$ answers [$ record ->questionid ][$ record ->choiceid ] = answer \answer::create_from_data ($ record );
@@ -637,6 +724,11 @@ private function mkresavg($sort, $stravgvalue='') {
637
724
$ content = $ contents ->text ;
638
725
}
639
726
}
727
+ if (isset ($ contentobj ->content ) &&
728
+ \mod_questionnaire \question \choice::content_other_choice_display ($ contentobj ->content )) {
729
+ $ othertext = \mod_questionnaire \question \choice::content_other_choice_display ($ contentobj ->content );
730
+ $ content = $ othertext . ' ' . clean_text ($ content );
731
+ }
640
732
if ($ osgood ) {
641
733
$ choicecol1 = new \stdClass ();
642
734
$ choicecol1 ->width = $ header1 ->width ;
@@ -761,15 +853,21 @@ private function mkrescount($rids, $rows, $sort) {
761
853
$ rsql = ' AND response_id ' . $ rsql ;
762
854
}
763
855
764
- array_unshift ($ params , $ this ->question ->id ); // This is question_id.
765
- $ sql = 'SELECT r.id, c.content, r.rankvalue, c.id AS choiceid ' .
766
- 'FROM {questionnaire_quest_choice} c , ' .
767
- '{questionnaire_response_rank} r ' .
768
- 'WHERE c.question_id = ? ' .
769
- ' AND r.question_id = c.question_id ' .
770
- ' AND r.choice_id = c.id ' .
771
- $ rsql .
772
- ' ORDER BY choiceid, rankvalue ASC ' ;
856
+ // This is question_id.
857
+ array_push ($ params , $ this ->question ->id );
858
+ $ sql = "SELECT r.id,
859
+ CASE
860
+ WHEN c.content = '!other' THEN o.response
861
+ ELSE c.content
862
+ END as content, r.rankvalue, c.id AS choiceid
863
+ FROM {questionnaire_quest_choice} c
864
+ INNER JOIN { " . static ::response_table () . "} r ON r.question_id = c.question_id
865
+ AND r.choice_id = c.id {$ rsql }
866
+ LEFT JOIN {questionnaire_response_other} o ON o.choice_id = c.id
867
+ AND o.response_id = r.response_id
868
+ AND o.question_id = c.question_id
869
+ WHERE c.question_id = ? AND (c.content != '!other' OR (o.response IS NOT NULL AND o.response <> ''))
870
+ ORDER BY choiceid, rankvalue ASC " ;
773
871
$ choices = $ DB ->get_records_sql ($ sql , $ params );
774
872
775
873
// Sort rows (results) by average value.
@@ -799,10 +897,10 @@ private function mkrescount($rids, $rows, $sort) {
799
897
if (!empty ($ this ->question ->nameddegrees )) {
800
898
$ rankvalue = array_flip (array_keys ($ this ->question ->nameddegrees ));
801
899
}
802
- foreach ($ rows as $ row ) {
900
+ foreach ($ rows as $ key => $ row ) {
803
901
$ choiceid = $ row ->id ;
804
902
foreach ($ choices as $ choice ) {
805
- if ($ choice ->choiceid == $ choiceid ) {
903
+ if ($ choice ->choiceid == $ choiceid && $ choice -> content === $ key ) {
806
904
$ n = 0 ;
807
905
for ($ i = 1 ; $ i <= $ nbranks ; $ i ++) {
808
906
if ((isset ($ rankvalue [$ choice ->rankvalue ]) && ($ rankvalue [$ choice ->rankvalue ] == ($ i - 1 ))) ||
@@ -893,17 +991,23 @@ private function mkrescount($rids, $rows, $sort) {
893
991
// Ensure there are two bits of content.
894
992
list ($ content , $ contentright ) = array_merge (preg_split ('/[|]/ ' , $ content ), array (' ' ));
895
993
$ header = reset ($ pagetags ->totals ->headers );
994
+ if (isset ($ rows [$ content ]) && isset ($ rows [$ content ]->isother ) && $ rows [$ content ]->isother ) {
995
+ $ content = get_string ('other ' , 'questionnaire ' ) . ' ' . $ content ;
996
+ }
896
997
$ totalcols [] = (object )['align ' => $ header ->align ,
897
- 'text ' => format_text ($ content , FORMAT_HTML , ['noclean ' => true ])];
998
+ 'text ' => format_text ($ content , FORMAT_HTML , ['noclean ' => true , ' filter ' => false ])];
898
999
} else {
899
1000
// Eliminate potentially short-named choices.
900
1001
$ contents = questionnaire_choice_values ($ content );
901
1002
if ($ contents ->modname ) {
902
1003
$ content = $ contents ->text ;
903
1004
}
1005
+ if (isset ($ rows [$ content ]) && isset ($ rows [$ content ]->isother ) && $ rows [$ content ]->isother ) {
1006
+ $ content = get_string ('other ' , 'questionnaire ' ) . ' ' . $ content ;
1007
+ }
904
1008
$ header = reset ($ pagetags ->totals ->headers );
905
1009
$ totalcols [] = (object )['align ' => $ header ->align ,
906
- 'text ' => format_text ($ content , FORMAT_HTML , ['noclean ' => true ])];
1010
+ 'text ' => format_text ($ content , FORMAT_HTML , ['noclean ' => true , ' filter ' => false ])];
907
1011
}
908
1012
// Display ranks/rates numbers.
909
1013
$ maxrank = max ($ rank );
0 commit comments