forked from PoetOS/moodle-mod_questionnaire
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Questionnaire: amend the 'Scale' question so that if you have 'Other'…
…, there's a text field underneath
- Loading branch information
toanlam
committed
Sep 4, 2024
1 parent
cf20dca
commit 75ba460
Showing
6 changed files
with
175 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -336,8 +336,21 @@ protected function question_survey_display($response, $descendantsdata, $blankqu | |
if ($this->osgood_rate_scale()) { | ||
list($content, $contentright) = array_merge(preg_split('/[|]/', $content), array(' ')); | ||
} | ||
$cols[] = ['colstyle' => 'text-align: '.$textalign.';', | ||
'coltext' => format_text($content, FORMAT_HTML, ['noclean' => true]).' ']; | ||
if ($choice->is_other_choice()) { | ||
$othertext = $choice->other_choice_display(); | ||
$oname = $cid . '_qother'; | ||
$oid = $cid . '-other'; | ||
$odata = isset($response->answers[$this->id][$cid]) ? $response->answers[$this->id][$cid]->value : ''; | ||
if (isset($odata)) { | ||
$ovalue = stripslashes($odata); | ||
} | ||
$content = $othertext; | ||
$cols[] = ['oname' => $oname, 'oid' => $oid, 'ovalue' => $ovalue,'colstyle' => 'text-align: '.$textalign.';', | ||
This comment has been minimized.
Sorry, something went wrong. |
||
'coltext' => format_text($content, FORMAT_HTML, ['noclean' => true]).' ']; | ||
This comment has been minimized.
Sorry, something went wrong.
tailetan
|
||
} else { | ||
$cols[] = ['colstyle' => 'text-align: '.$textalign.';', | ||
'coltext' => format_text($content, FORMAT_HTML, ['noclean' => true]).' ']; | ||
} | ||
|
||
$bg = 'c0 raterow'; | ||
$hasnotansweredchoice = false; | ||
|
@@ -512,6 +525,12 @@ protected function response_survey_display($response) { | |
if ($this->osgood_rate_scale()) { | ||
list($content, $contentright) = array_merge(preg_split('/[|]/', $content), array(' ')); | ||
} | ||
if ($choice->is_other_choice()) { | ||
$content = $choice->other_choice_display(); | ||
if (isset($response->answers[$this->id][$cid]->otheresponse)) { | ||
$rowobj->othercontent = $response->answers[$this->id][$cid]->otheresponse; | ||
} | ||
} | ||
$rowobj->content = format_text($content, FORMAT_HTML, ['noclean' => true]).' '; | ||
$bg = 'c0'; | ||
$cols = []; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,6 +132,14 @@ public function insert_response($responsedata) { | |
$record->choice_id = $answer->choiceid; | ||
$record->rankvalue = $answer->value; | ||
$resid = $DB->insert_record(static::response_table(), $record); | ||
if (isset($responsedata->{$answer->choiceid . '_qother'})) { | ||
$otherrecord = new \stdClass(); | ||
$otherrecord->response_id = $response->id; | ||
$otherrecord->question_id = $this->question->id; | ||
$otherrecord->choice_id = $answer->choiceid; | ||
$otherrecord->response = $responsedata->{$answer->choiceid . '_qother'}; | ||
$DB->insert_record('questionnaire_response_other', $otherrecord); | ||
} | ||
} | ||
} | ||
return $resid; | ||
|
@@ -153,7 +161,7 @@ public function get_results($rids=false, $anonymous=false) { | |
$rsql = ' AND response_id ' . $rsql; | ||
} | ||
|
||
$select = 'question_id=' . $this->question->id . ' AND content NOT LIKE \'!other%\' ORDER BY id ASC'; | ||
$select = 'question_id=' . $this->question->id . ' ORDER BY id ASC'; | ||
if ($rows = $DB->get_records_select('questionnaire_quest_choice', $select)) { | ||
foreach ($rows as $row) { | ||
$this->counts[$row->content] = new \stdClass(); | ||
|
@@ -201,16 +209,25 @@ public function get_results($rids=false, $anonymous=false) { | |
GROUP BY c2.id) a ON a.id = c.id | ||
order by c.id"; | ||
$results = $DB->get_records_sql($sql, array_merge(array($this->question->id, $this->question->id), $params)); | ||
if (!empty ($rankvalue)) { | ||
foreach ($results as $key => $result) { | ||
if (isset($value[$key])) { | ||
$result->averagevalue = $value[$key] / $result->num; | ||
if (!empty($results)) { | ||
$choiceids = array_keys($results); | ||
$otherresultcontent = self::get_other_choice($choiceids); | ||
if (!empty ($rankvalue)) { | ||
foreach ($results as $key => $result) { | ||
if (isset($value[$key])) { | ||
$result->averagevalue = $value[$key] / $result->num; | ||
} | ||
} | ||
} | ||
} | ||
// Reindex by 'content'. Can't do this from the query as it won't work with MS-SQL. | ||
foreach ($results as $key => $result) { | ||
$results[$result->content] = $result; | ||
if ($result->id) { | ||
if (isset($otherresultcontent[$result->id])) { | ||
$results[$result->content]->content = $otherresultcontent[$result->id]; | ||
} | ||
} | ||
unset($results[$key]); | ||
} | ||
return $results; | ||
|
@@ -224,17 +241,63 @@ public function get_results($rids=false, $anonymous=false) { | |
WHERE c2.question_id = ? AND a2.question_id = ? AND a2.choice_id = c2.id AND a2.rankvalue >= 0{$rsql} | ||
GROUP BY c2.id) a ON a.id = c.id"; | ||
$results = $DB->get_records_sql($sql, array_merge(array($this->question->id, $this->question->id), $params)); | ||
if (!empty($results)) { | ||
$choiceids = array_keys($results); | ||
$otherresultcontent = self::get_other_choice($choiceids); | ||
} | ||
|
||
// Formula to calculate the best ranking order. | ||
$nbresponses = count($rids); | ||
foreach ($results as $key => $result) { | ||
$result->average = ($result->sum + ($nbresponses - $result->num) * ($this->length + 1)) / $nbresponses; | ||
if (isset($this->length)) { | ||
$result->average = ($result->sum + ($nbresponses - $result->num) * ($this->length + 1)) / $nbresponses; | ||
} else { | ||
$result->average = ($result->sum + ($nbresponses - $result->num) * 1 ) / $nbresponses; | ||
} | ||
$results[$result->content] = $result; | ||
if (isset($otherresultcontent[$result->id])) { | ||
$results[$result->content]->content = $otherresultcontent[$result->id]; | ||
} | ||
unset($results[$key]); | ||
} | ||
return $results; | ||
} | ||
} | ||
|
||
/** | ||
* @param $choiceids | ||
* @return array | ||
*/ | ||
public function get_other_choice($choiceids) { | ||
global $DB; | ||
list($othersql, $params) = $DB->get_in_or_equal($choiceids); | ||
$osql = "SELECT ro.*,rr.rankvalue FROM {questionnaire_response_other} ro | ||
INNER JOIN {".static::response_table()."} rr ON ro.choice_id = rr.choice_id | ||
AND ro.question_id = rr.question_id AND rr.response_id = ro.response_id | ||
WHERE ro.choice_id $othersql | ||
"; | ||
$otheresults = $DB->get_records_sql($osql, $params); | ||
$otherresultcontent = []; | ||
if (!empty($otheresults)) { | ||
foreach ($otheresults as $key => $oresult) { | ||
if (array_key_last($otheresults) == $key) { | ||
if (isset($otherresultcontent[$oresult->choice_id])) { | ||
$otherresultcontent[$oresult->choice_id] .= $oresult->response . '(' . $oresult->rankvalue . ')'; | ||
} else { | ||
$otherresultcontent[$oresult->choice_id] = $oresult->response . '(' . $oresult->rankvalue . ')'; | ||
} | ||
} else { | ||
if (isset($otherresultcontent[$oresult->choice_id])) { | ||
$otherresultcontent[$oresult->choice_id] .= $oresult->response . '(' . $oresult->rankvalue . '), '; | ||
} else { | ||
$otherresultcontent[$oresult->choice_id] = $oresult->response . '(' . $oresult->rankvalue . '), '; | ||
} | ||
} | ||
} | ||
} | ||
return $otherresultcontent; | ||
} | ||
|
||
/** | ||
* Provide the feedback scores for all requested response id's. This should be provided only by questions that provide feedback. | ||
* @param array $rids | ||
|
@@ -417,9 +480,11 @@ public static function response_answers_by_question($rid) { | |
global $DB; | ||
|
||
$answers = []; | ||
$sql = 'SELECT id, response_id as responseid, question_id as questionid, choice_id as choiceid, rankvalue as value ' . | ||
'FROM {' . static::response_table() .'} ' . | ||
'WHERE response_id = ? '; | ||
$sql = 'SELECT r.id, r.response_id as responseid, r.question_id as questionid, r.choice_id as choiceid, r.rankvalue as value, rt.response as otheresponse ' . | ||
This comment has been minimized.
Sorry, something went wrong.
tailetan
|
||
'FROM {' . static::response_table() .'} r ' . | ||
'LEFT JOIN {questionnaire_response_other} rt ON rt.choice_id = r.choice_id | ||
AND r.question_id = rt.question_id AND r.response_id = rt.response_id' . | ||
' WHERE r.response_id = ? '; | ||
$records = $DB->get_records_sql($sql, [$rid]); | ||
foreach ($records as $record) { | ||
$answers[$record->questionid][$record->choiceid] = answer\answer::create_from_data($record); | ||
|
@@ -637,6 +702,9 @@ private function mkresavg($sort, $stravgvalue='') { | |
$content = $contents->text; | ||
} | ||
} | ||
if (\mod_questionnaire\question\choice::content_other_choice_display($content)) { | ||
$content = \mod_questionnaire\question\choice::content_other_choice_display($content); | ||
} | ||
if ($osgood) { | ||
$choicecol1 = new \stdClass(); | ||
$choicecol1->width = $header1->width; | ||
|
@@ -893,17 +961,25 @@ private function mkrescount($rids, $rows, $sort) { | |
// Ensure there are two bits of content. | ||
list($content, $contentright) = array_merge(preg_split('/[|]/', $content), array(' ')); | ||
$header = reset($pagetags->totals->headers); | ||
$responsetxt = \mod_questionnaire\question\choice::content_other_choice_display($content); | ||
if (isset($rows[$content]) && $responsetxt) { | ||
$content = $responsetxt . $rows[$content]->content; | ||
} | ||
$totalcols[] = (object)['align' => $header->align, | ||
'text' => format_text($content, FORMAT_HTML, ['noclean' => true])]; | ||
'text' => format_text($content, FORMAT_HTML, ['noclean' => true, 'filter' => false])]; | ||
} else { | ||
// Eliminate potentially short-named choices. | ||
$contents = questionnaire_choice_values($content); | ||
if ($contents->modname) { | ||
$content = $contents->text; | ||
} | ||
$responsetxt = \mod_questionnaire\question\choice::content_other_choice_display($content); | ||
if (isset($rows[$content]) && $responsetxt) { | ||
$content = $responsetxt . $rows[$content]->content; | ||
} | ||
$header = reset($pagetags->totals->headers); | ||
$totalcols[] = (object)['align' => $header->align, | ||
'text' => format_text($content, FORMAT_HTML, ['noclean' => true])]; | ||
'text' => format_text($content, FORMAT_HTML, ['noclean' => true, 'filter' => false])]; | ||
} | ||
// Display ranks/rates numbers. | ||
$maxrank = max($rank); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
@mod @mod_questionnaire | ||
Feature: Rate scale questions have Other option | ||
In order to display an Other choice in rate question | ||
As a teacher | ||
the 'Other' option should display with textbox next to it in the question view | ||
|
||
@javascript | ||
Scenario: Create a rate question type with an 'Other' choice and verify the response exists | ||
Given the following "users" exist: | ||
| username | firstname | lastname | email | | ||
| teacher1 | Teacher | 1 | teacher1@example.com | | ||
| student1 | Student | 1 | student1@example.com | | ||
And the following "courses" exist: | ||
| fullname | shortname | category | | ||
| Course 1 | C1 | 0 | | ||
And the following "course enrolments" exist: | ||
| user | course | role | | ||
| teacher1 | C1 | editingteacher | | ||
| student1 | C1 | student | | ||
And the following "activities" exist: | ||
| activity | name | description | course | idnumber | | ||
| questionnaire | Test questionnaire | Test questionnaire description | C1 | questionnaire0 | | ||
And I log in as "teacher1" | ||
And I am on "Course 1" course homepage | ||
And I follow "Test questionnaire" | ||
And I navigate to "Questions" in current page administration | ||
And I add a "Rate (scale 1..5)" question and I fill the form with: | ||
| Question Name | Q1 | | ||
| Yes | y | | ||
| Nb of scale items | 3 | | ||
| Type of rate scale | No duplicate choices | | ||
| Question Text | What are your top three movies? | | ||
| Possible answers | Star Wars,Casablanca,Airplane,Citizen Kane,Anchorman,!other | | ||
Then I should see "position 1" | ||
And I should see "[Rate (scale 1..5)] (Q1)" | ||
And I should see "What are your top three movies?" | ||
And I log out | ||
|
||
And I log in as "student1" | ||
And I am on "Course 1" course homepage | ||
And I follow "Test questionnaire" | ||
And I navigate to "Answer the questions..." in current page administration | ||
Then I should see "Test questionnaire" | ||
And I should see "What are your top three movies?" | ||
And I click on "Row 2, Star Wars: Column 2, 1." "radio" | ||
And I click on "Row 4, Airplane: Column 3, 2." "radio" | ||
And I click on "Row 3, Casablanca: Column 4, 3." "radio" | ||
And I click on "Row 7, !other: Column 4, 3." "radio" | ||
And I set the field with xpath "//input[contains(@name,'qother')]" to "Once Upon a Time" | ||
And I press "Submit questionnaire" | ||
And I press "Continue" | ||
Then I should see "Once Upon a Time" | ||
And I log out | ||
And I log in as "teacher1" | ||
And I am on "Course 1" course homepage | ||
And I follow "Test questionnaire" | ||
And I navigate to "View all responses" in current page administration | ||
Then I should see "Once Upon a Time(3)" |
add a white space after $ovalue,