Skip to content

Commit 716df66

Browse files
committed
2023-01-16 AC: Adds more OOP extensibility to mod_questionnaire.
1 parent 40aca37 commit 716df66

9 files changed

+166
-41
lines changed

classes/question/question.php

+22-3
Original file line numberDiff line numberDiff line change
@@ -181,20 +181,39 @@ public function __construct($id = 0, $question = null, $context = null, $params
181181
}
182182

183183
/**
184-
* Short name for this question type - no spaces, etc..
184+
* Short name for this question type - no spaces, etc.
185185
* @return string
186186
*/
187187
abstract public function helpname();
188188

189189
/**
190-
* Build a question from data.
190+
* Build a question from id.
191191
* @param int $qtype
192192
* @param int|array $qdata
193193
* @param \stdClass $context
194194
* @return mixed
195195
*/
196196
public static function question_builder($qtype, $qdata = null, $context = null) {
197-
$qclassname = '\\mod_questionnaire\\question\\'.self::qtypename($qtype);
197+
$qclassname = '\\mod_questionnaire\\question\\' . self::qtypename($qtype);
198+
$qid = 0;
199+
if (!empty($qdata) && is_array($qdata)) {
200+
$qdata = (object)$qdata;
201+
} else if (!empty($qdata) && is_int($qdata)) {
202+
$qid = $qdata;
203+
}
204+
return new $qclassname($qid, $qdata, $context, ['type_id' => $qtype]);
205+
}
206+
207+
/**
208+
* Build a question from FQCN.
209+
* @param string $qtypefqcn
210+
* @param int $qtype
211+
* @param int|array $qdata
212+
* @param \stdClass $context
213+
* @return mixed
214+
*/
215+
public static function question_builder_fqcn($qtypefqcn, $qtype, $qdata = null, $context = null) {
216+
$qclassname = (string) $qtypefqcn;
198217
$qid = 0;
199218
if (!empty($qdata) && is_array($qdata)) {
200219
$qdata = (object)$qdata;

db/install.php

+11
Original file line numberDiff line numberDiff line change
@@ -35,76 +35,87 @@ function xmldb_questionnaire_install() {
3535
$questiontype->type = 'Yes/No';
3636
$questiontype->has_choices = 'n';
3737
$questiontype->response_table = 'response_bool';
38+
$questiontype->fqcn = '\\mod_questionnaire\\question\\yesno';
3839
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
3940

4041
$questiontype = new stdClass();
4142
$questiontype->typeid = 2;
4243
$questiontype->type = 'Text Box';
4344
$questiontype->has_choices = 'n';
4445
$questiontype->response_table = 'response_text';
46+
$questiontype->fqcn = '\\mod_questionnaire\\question\\text';
4547
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
4648

4749
$questiontype = new stdClass();
4850
$questiontype->typeid = 3;
4951
$questiontype->type = 'Essay Box';
5052
$questiontype->has_choices = 'n';
5153
$questiontype->response_table = 'response_text';
54+
$questiontype->fqcn = '\\mod_questionnaire\\question\\essay';
5255
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
5356

5457
$questiontype = new stdClass();
5558
$questiontype->typeid = 4;
5659
$questiontype->type = 'Radio Buttons';
5760
$questiontype->has_choices = 'y';
5861
$questiontype->response_table = 'resp_single';
62+
$questiontype->fqcn = '\\mod_questionnaire\\question\\radio';
5963
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
6064

6165
$questiontype = new stdClass();
6266
$questiontype->typeid = 5;
6367
$questiontype->type = 'Check Boxes';
6468
$questiontype->has_choices = 'y';
6569
$questiontype->response_table = 'resp_multiple';
70+
$questiontype->fqcn = '\\mod_questionnaire\\question\\check';
6671
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
6772

6873
$questiontype = new stdClass();
6974
$questiontype->typeid = 6;
7075
$questiontype->type = 'Dropdown Box';
7176
$questiontype->has_choices = 'y';
7277
$questiontype->response_table = 'resp_single';
78+
$questiontype->fqcn = '\\mod_questionnaire\\question\\drop';
7379
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
7480

7581
$questiontype = new stdClass();
7682
$questiontype->typeid = 8;
7783
$questiontype->type = 'Rate (scale 1..5)';
7884
$questiontype->has_choices = 'y';
7985
$questiontype->response_table = 'response_rank';
86+
$questiontype->fqcn = '\\mod_questionnaire\\question\\rate';
8087
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
8188

8289
$questiontype = new stdClass();
8390
$questiontype->typeid = 9;
8491
$questiontype->type = 'Date';
8592
$questiontype->has_choices = 'n';
8693
$questiontype->response_table = 'response_date';
94+
$questiontype->fqcn = '\\mod_questionnaire\\question\\date';
8795
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
8896

8997
$questiontype = new stdClass();
9098
$questiontype->typeid = 10;
9199
$questiontype->type = 'Numeric';
92100
$questiontype->has_choices = 'n';
93101
$questiontype->response_table = 'response_text';
102+
$questiontype->fqcn = '\\mod_questionnaire\\question\\numerical';
94103
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
95104

96105
$questiontype = new stdClass();
97106
$questiontype->typeid = 99;
98107
$questiontype->type = 'Page Break';
99108
$questiontype->has_choices = 'n';
100109
$questiontype->response_table = '';
110+
$questiontype->fqcn = '\\mod_questionnaire\\question\\pagebreak';
101111
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
102112

103113
$questiontype = new stdClass();
104114
$questiontype->typeid = 100;
105115
$questiontype->type = 'Section Text';
106116
$questiontype->has_choices = 'n';
107117
$questiontype->response_table = '';
118+
$questiontype->fqcn = '\\mod_questionnaire\\question\\sectiontext';
108119
$id = $DB->insert_record('questionnaire_question_type', $questiontype);
109120

110121
}

db/install.xml

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
<FIELD NAME="type" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false"/>
106106
<FIELD NAME="has_choices" TYPE="char" LENGTH="1" NOTNULL="true" DEFAULT="y" SEQUENCE="false"/>
107107
<FIELD NAME="response_table" TYPE="char" LENGTH="32" NOTNULL="false" SEQUENCE="false"/>
108+
<FIELD NAME="fqcn" TYPE="char" LENGTH="256" NOTNULL="true" SEQUENCE="false" DEFAULT="fqcn"/>
108109
</FIELDS>
109110
<KEYS>
110111
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>

db/upgrade.php

+61
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,67 @@ function xmldb_questionnaire_upgrade($oldversion=0) {
983983
upgrade_mod_savepoint(true, 2020062301, 'questionnaire');
984984
}
985985

986+
if ($oldversion < 2022121501) {
987+
// Add new FQCN configuration for question types.
988+
$table = new xmldb_table('questionnaire_question_type');
989+
$field = new xmldb_field('fqcn', XMLDB_TYPE_CHAR, '256', null, XMLDB_NOTNULL, null, 'fqcn', null);
990+
991+
// Conditionally launch add field.
992+
if (!$dbman->field_exists($table, $field)) {
993+
$dbman->add_field($table, $field);
994+
}
995+
996+
$qtypes = $DB->get_recordset('questionnaire_question_type', null);
997+
998+
foreach ($qtypes as $questiontype) {
999+
$questiontype->fqcn = '\\mod_questionnaire\\question\\';
1000+
switch ($questiontype->typeid) {
1001+
case 1:
1002+
$questiontype->fqcn .= 'yesno';
1003+
break;
1004+
case 2:
1005+
$questiontype->fqcn .= 'text';
1006+
break;
1007+
case 3:
1008+
$questiontype->fqcn .= 'essay';
1009+
break;
1010+
case 4:
1011+
$questiontype->fqcn .= 'radio';
1012+
break;
1013+
case 5:
1014+
$questiontype->fqcn .= 'check';
1015+
break;
1016+
case 6:
1017+
$questiontype->fqcn .= 'drop';
1018+
break;
1019+
case 8:
1020+
$questiontype->fqcn .= 'rate';
1021+
break;
1022+
case 9:
1023+
$questiontype->fqcn .= 'date';
1024+
break;
1025+
case 10:
1026+
$questiontype->fqcn .= 'numerical';
1027+
break;
1028+
case 99:
1029+
$questiontype->fqcn .= 'pagebreak';
1030+
break;
1031+
case 100:
1032+
$questiontype->fqcn .= 'sectiontext';
1033+
break;
1034+
default:
1035+
$unknowntype = true;
1036+
}
1037+
1038+
if (!$unknowntype) {
1039+
$DB->update_record('questionnaire_question_type', $questiontype);
1040+
}
1041+
}
1042+
1043+
// Questionnaire savepoint reached.
1044+
upgrade_mod_savepoint(true, 2022121501, 'questionnaire');
1045+
}
1046+
9861047
return $result;
9871048
}
9881049

lang/en/questionnaire.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
$string['downloadtextformat_link'] = 'mod/questionnaire/report#Download_in_text_format';
150150
$string['downloadtypes'] = 'Report type';
151151
$string['dropdown'] = 'Dropdown Box';
152+
$string['dropdownbox'] = 'Dropdown Box';
152153
$string['dropdown_help'] = 'There is no real advantage to using the Dropdown Box over using the Radio Buttons
153154
except perhaps for longish lists of options, to save screen space.';
154155
$string['dropdown_link'] = 'mod/questionnaire/questions#Dropdown_Box';
@@ -558,8 +559,8 @@
558559
$string['search:activity'] = 'Questionnaire - activity information';
559560
$string['search:question'] = 'Questionnaire - questions';
560561
$string['section'] = 'Description';
561-
$string['sectionbreak'] = '----- Page Break -----';
562-
$string['sectionbreak_help'] = '----- Page Break -----';
562+
$string['pagebreak'] = '----- Page Break -----';
563+
$string['pagebreak_help'] = '----- Page Break -----';
563564
$string['sectionsnotset'] = 'You must select at least ONE question per section!<br />Section(s) not selected: {$a}';
564565
$string['sectiontext'] = 'Label';
565566
$string['sectiontext_help'] = 'This is not a question but a (short) text which will be displayed to introduce a series of questions.';

locallib.php

+57-28
Original file line numberDiff line numberDiff line change
@@ -466,34 +466,62 @@ function questionnaire_get_survey_select($courseid=0, $type='') {
466466
* @param int $id
467467
* @return lang_string|mixed|string
468468
* @throws coding_exception
469+
* @deprecated Please use questionnaire_get_type_name() instead.
469470
*/
470-
function questionnaire_get_type ($id) {
471-
switch ($id) {
472-
case 1:
473-
return get_string('yesno', 'questionnaire');
474-
case 2:
475-
return get_string('textbox', 'questionnaire');
476-
case 3:
477-
return get_string('essaybox', 'questionnaire');
478-
case 4:
479-
return get_string('radiobuttons', 'questionnaire');
480-
case 5:
481-
return get_string('checkboxes', 'questionnaire');
482-
case 6:
483-
return get_string('dropdown', 'questionnaire');
484-
case 8:
485-
return get_string('ratescale', 'questionnaire');
486-
case 9:
487-
return get_string('date', 'questionnaire');
488-
case 10:
489-
return get_string('numeric', 'questionnaire');
490-
case 100:
491-
return get_string('sectiontext', 'questionnaire');
492-
case 99:
493-
return get_string('sectionbreak', 'questionnaire');
494-
default:
495-
return $id;
471+
function questionnaire_get_type($id) {
472+
return questionnaire_get_type_name($id);
473+
}
474+
475+
/**
476+
* Return the language string for the specified question type.
477+
* @param int $id
478+
* @return lang_string|mixed|string
479+
* @throws coding_exception
480+
*/
481+
function questionnaire_get_type_name($id) {
482+
global $DB;
483+
484+
$qtypeobject = $DB->get_record('questionnaire_question_type', ['typeid' => $id], '*', MUST_EXIST);
485+
486+
$qtype = preg_replace("/[^a-zA-Z]+/", "", strtolower($qtypeobject->type));
487+
488+
$qtypeobjectnamespace = explode('\\', questionnaire_get_question_type_object($id)->fqcn)[1];
489+
490+
return get_string($qtype, $qtypeobjectnamespace);
491+
}
492+
493+
/**
494+
* Return the language string for all question types.
495+
* @return array
496+
* @throws coding_exception
497+
*/
498+
function questionnaire_get_all_question_types() {
499+
global $DB;
500+
501+
$qtypes = $DB->get_records('questionnaire_question_type', [], 'typeid',
502+
'typeid, type, has_choices, response_table');
503+
504+
foreach ($qtypes as $qtype) {
505+
$qtypenames[$qtype->typeid] = $qtype->type;
496506
}
507+
508+
return $qtypenames;
509+
}
510+
511+
/**
512+
* Return an object of the specified question type.
513+
* @param int $id
514+
* @return stdClass
515+
* @throws coding_exception
516+
*/
517+
function questionnaire_get_question_type_object($id) {
518+
global $DB;
519+
520+
$qtypeobject = $DB->get_record('questionnaire_question_type', ['typeid' => $id], '*', MUST_EXIST);
521+
522+
$qtype = preg_replace("/[^a-zA-Z]+/", "", strtolower($qtypeobject->type));
523+
524+
return $qtypeobject;
497525
}
498526

499527
/**
@@ -876,7 +904,8 @@ function questionnaire_prep_for_questionform($questionnaire, $qid, $qtype) {
876904
}
877905
}
878906
} else {
879-
$question = \mod_questionnaire\question\question::question_builder($qtype);
907+
$question = questionnaire_get_question_type_object($qtype);
908+
$question = \mod_questionnaire\question\question::question_builder_fqcn($question->fqcn, $qtype);
880909
$question->sid = $questionnaire->survey->id;
881910
$question->id = $questionnaire->cm->id;
882911
$question->type_id = $qtype;
@@ -890,7 +919,7 @@ function questionnaire_prep_for_questionform($questionnaire, $qid, $qtype) {
890919
}
891920

892921
/**
893-
* Get the standard page contructs and check for validity.
922+
* Get the standard page constructs and check for validity.
894923
* @param int $id The coursemodule id.
895924
* @param int $a The module instance id.
896925
* @return array An array with the $cm, $course, and $questionnaire records in that order.

questionnaire.class.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ public function add_questions($sid = false) {
139139
$sec = 1;
140140
$isbreak = false;
141141
foreach ($records as $record) {
142-
143-
$this->questions[$record->id] = \mod_questionnaire\question\question::question_builder($record->type_id,
144-
$record, $this->context);
142+
$qtypeobject = questionnaire_get_question_type_object($record->type_id);
143+
$this->questions[$record->id] = \mod_questionnaire\question\question::question_builder_fqcn($qtypeobject->fqcn,
144+
$record->type_id, $record, $this->context);
145145

146146
if ($record->type_id != QUESPAGEBREAK) {
147147
$this->questionsbysec[$sec][] = $record->id;
@@ -3018,7 +3018,8 @@ protected function get_survey_all_responses($rid = '', $userid = '', $groupid =
30183018
}
30193019

30203020
foreach ($uniquetypes as $type) {
3021-
$question = \mod_questionnaire\question\question::question_builder($type);
3021+
$qtypeobject = questionnaire_get_question_type_object($type);
3022+
$question = \mod_questionnaire\question\question::question_builder_fqcn($qtypeobject->fqcn, $type);
30223023
if (!isset($question->responsetype)) {
30233024
continue;
30243025
}

questions.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120

121121
// Log question deleted event.
122122
$context = context_module::instance($questionnaire->cm->id);
123-
$questiontype = \mod_questionnaire\question\question::qtypename($questionnaire->questions[$qid]->type_id);
123+
$questiontype = questionnaire_get_all_question_types()[$questionnaire->questions[$qid]->type_id];
124124
$params = array(
125125
'context' => $context,
126126
'courseid' => $questionnaire->course->id,
@@ -220,7 +220,8 @@
220220
$questionrec->surveyid = $qformdata->sid;
221221
$questionrec->type_id = QUESPAGEBREAK;
222222
$questionrec->content = 'break';
223-
$question = \mod_questionnaire\question\question::question_builder(QUESPAGEBREAK);
223+
$qtypeobject = questionnaire_get_question_type_object(QUESPAGEBREAK);
224+
$question = \mod_questionnaire\question\question::question_builder($qtypeobject->fqcn, QUESPAGEBREAK);
224225
$question->add($questionrec);
225226
$reload = true;
226227
} else {
@@ -296,7 +297,7 @@
296297
// Log question created event.
297298
if (isset($qformdata)) {
298299
$context = context_module::instance($questionnaire->cm->id);
299-
$questiontype = \mod_questionnaire\question\question::qtypename($qformdata->type_id);
300+
$questiontype = questionnaire_get_all_question_types()[$qformdata->type_id];
300301
$params = array(
301302
'context' => $context,
302303
'courseid' => $questionnaire->course->id,
@@ -413,5 +414,6 @@
413414
} else {
414415
$questionnaire->page->add_to_page('formarea', $questionsform->render());
415416
}
417+
416418
echo $questionnaire->renderer->render($questionnaire->page);
417419
echo $questionnaire->renderer->footer();

0 commit comments

Comments
 (0)