Skip to content

Commit

Permalink
2023-01-16 AC: Adds more OOP extensibility to mod_questionnaire.
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewscaya committed Jan 25, 2023
1 parent 40aca37 commit ed117df
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 41 deletions.
25 changes: 22 additions & 3 deletions classes/question/question.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,20 +181,39 @@ public function __construct($id = 0, $question = null, $context = null, $params
}

/**
* Short name for this question type - no spaces, etc..
* Short name for this question type - no spaces, etc.
* @return string
*/
abstract public function helpname();

/**
* Build a question from data.
* Build a question from id.
* @param int $qtype
* @param int|array $qdata
* @param \stdClass $context
* @return mixed
*/
public static function question_builder($qtype, $qdata = null, $context = null) {
$qclassname = '\\mod_questionnaire\\question\\'.self::qtypename($qtype);
$qclassname = '\\mod_questionnaire\\question\\' . self::qtypename($qtype);
$qid = 0;
if (!empty($qdata) && is_array($qdata)) {
$qdata = (object)$qdata;
} else if (!empty($qdata) && is_int($qdata)) {
$qid = $qdata;
}
return new $qclassname($qid, $qdata, $context, ['type_id' => $qtype]);
}

/**
* Build a question from FQCN.
* @param string $qtypefqcn
* @param int $qtype
* @param int|array $qdata
* @param \stdClass $context
* @return mixed
*/
public static function question_builder_fqcn($qtypefqcn, $qtype, $qdata = null, $context = null) {
$qclassname = (string) $qtypefqcn;
$qid = 0;
if (!empty($qdata) && is_array($qdata)) {
$qdata = (object)$qdata;
Expand Down
11 changes: 11 additions & 0 deletions db/install.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,76 +35,87 @@ function xmldb_questionnaire_install() {
$questiontype->type = 'Yes/No';
$questiontype->has_choices = 'n';
$questiontype->response_table = 'response_bool';
$questiontype->fqcn = '\\mod_questionnaire\\question\\yesno';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 2;
$questiontype->type = 'Text Box';
$questiontype->has_choices = 'n';
$questiontype->response_table = 'response_text';
$questiontype->fqcn = '\\mod_questionnaire\\question\\text';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 3;
$questiontype->type = 'Essay Box';
$questiontype->has_choices = 'n';
$questiontype->response_table = 'response_text';
$questiontype->fqcn = '\\mod_questionnaire\\question\\essay';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 4;
$questiontype->type = 'Radio Buttons';
$questiontype->has_choices = 'y';
$questiontype->response_table = 'resp_single';
$questiontype->fqcn = '\\mod_questionnaire\\question\\radio';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 5;
$questiontype->type = 'Check Boxes';
$questiontype->has_choices = 'y';
$questiontype->response_table = 'resp_multiple';
$questiontype->fqcn = '\\mod_questionnaire\\question\\check';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 6;
$questiontype->type = 'Dropdown Box';
$questiontype->has_choices = 'y';
$questiontype->response_table = 'resp_single';
$questiontype->fqcn = '\\mod_questionnaire\\question\\drop';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 8;
$questiontype->type = 'Rate (scale 1..5)';
$questiontype->has_choices = 'y';
$questiontype->response_table = 'response_rank';
$questiontype->fqcn = '\\mod_questionnaire\\question\\rate';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 9;
$questiontype->type = 'Date';
$questiontype->has_choices = 'n';
$questiontype->response_table = 'response_date';
$questiontype->fqcn = '\\mod_questionnaire\\question\\date';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 10;
$questiontype->type = 'Numeric';
$questiontype->has_choices = 'n';
$questiontype->response_table = 'response_text';
$questiontype->fqcn = '\\mod_questionnaire\\question\\numerical';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 99;
$questiontype->type = 'Page Break';
$questiontype->has_choices = 'n';
$questiontype->response_table = '';
$questiontype->fqcn = '\\mod_questionnaire\\question\\pagebreak';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

$questiontype = new stdClass();
$questiontype->typeid = 100;
$questiontype->type = 'Section Text';
$questiontype->has_choices = 'n';
$questiontype->response_table = '';
$questiontype->fqcn = '\\mod_questionnaire\\question\\sectiontext';
$id = $DB->insert_record('questionnaire_question_type', $questiontype);

}
1 change: 1 addition & 0 deletions db/install.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
<FIELD NAME="type" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="has_choices" TYPE="char" LENGTH="1" NOTNULL="true" DEFAULT="y" SEQUENCE="false"/>
<FIELD NAME="response_table" TYPE="char" LENGTH="32" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="fqcn" TYPE="char" LENGTH="256" NOTNULL="true" SEQUENCE="false" DEFAULT="fqcn"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand Down
61 changes: 61 additions & 0 deletions db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,67 @@ function xmldb_questionnaire_upgrade($oldversion=0) {
upgrade_mod_savepoint(true, 2020062301, 'questionnaire');
}

if ($oldversion < 2022121501) {
// Add new FQCN configuration for question types.
$table = new xmldb_table('questionnaire_question_type');
$field = new xmldb_field('fqcn', XMLDB_TYPE_CHAR, '256', null, XMLDB_NOTNULL, null, 'fqcn', null);

// Conditionally launch add field.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

$qtypes = $DB->get_recordset('questionnaire_question_type', null);

foreach ($qtypes as $questiontype) {
$questiontype->fqcn = '\\mod_questionnaire\\question\\';
switch ($questiontype->typeid) {
case 1:
$questiontype->fqcn .= 'yesno';
break;
case 2:
$questiontype->fqcn .= 'text';
break;
case 3:
$questiontype->fqcn .= 'essay';
break;
case 4:
$questiontype->fqcn .= 'radio';
break;
case 5:
$questiontype->fqcn .= 'check';
break;
case 6:
$questiontype->fqcn .= 'drop';
break;
case 8:
$questiontype->fqcn .= 'rate';
break;
case 9:
$questiontype->fqcn .= 'date';
break;
case 10:
$questiontype->fqcn .= 'numerical';
break;
case 99:
$questiontype->fqcn .= 'pagebreak';
break;
case 100:
$questiontype->fqcn .= 'sectiontext';
break;
default:
$unknowntype = true;
}

if (!$unknowntype) {
$DB->update_record('questionnaire_question_type', $questiontype);
}
}

// Questionnaire savepoint reached.
upgrade_mod_savepoint(true, 2022121501, 'questionnaire');
}

return $result;
}

Expand Down
5 changes: 3 additions & 2 deletions lang/en/questionnaire.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
$string['downloadtextformat_link'] = 'mod/questionnaire/report#Download_in_text_format';
$string['downloadtypes'] = 'Report type';
$string['dropdown'] = 'Dropdown Box';
$string['dropdownbox'] = 'Dropdown Box';
$string['dropdown_help'] = 'There is no real advantage to using the Dropdown Box over using the Radio Buttons
except perhaps for longish lists of options, to save screen space.';
$string['dropdown_link'] = 'mod/questionnaire/questions#Dropdown_Box';
Expand Down Expand Up @@ -558,8 +559,8 @@
$string['search:activity'] = 'Questionnaire - activity information';
$string['search:question'] = 'Questionnaire - questions';
$string['section'] = 'Description';
$string['sectionbreak'] = '----- Page Break -----';
$string['sectionbreak_help'] = '----- Page Break -----';
$string['pagebreak'] = '----- Page Break -----';
$string['pagebreak_help'] = '----- Page Break -----';
$string['sectionsnotset'] = 'You must select at least ONE question per section!<br />Section(s) not selected: {$a}';
$string['sectiontext'] = 'Label';
$string['sectiontext_help'] = 'This is not a question but a (short) text which will be displayed to introduce a series of questions.';
Expand Down
85 changes: 57 additions & 28 deletions locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -466,34 +466,62 @@ function questionnaire_get_survey_select($courseid=0, $type='') {
* @param int $id
* @return lang_string|mixed|string
* @throws coding_exception
* @deprecated Please use questionnaire_get_type_name() instead.
*/
function questionnaire_get_type ($id) {
switch ($id) {
case 1:
return get_string('yesno', 'questionnaire');
case 2:
return get_string('textbox', 'questionnaire');
case 3:
return get_string('essaybox', 'questionnaire');
case 4:
return get_string('radiobuttons', 'questionnaire');
case 5:
return get_string('checkboxes', 'questionnaire');
case 6:
return get_string('dropdown', 'questionnaire');
case 8:
return get_string('ratescale', 'questionnaire');
case 9:
return get_string('date', 'questionnaire');
case 10:
return get_string('numeric', 'questionnaire');
case 100:
return get_string('sectiontext', 'questionnaire');
case 99:
return get_string('sectionbreak', 'questionnaire');
default:
return $id;
function questionnaire_get_type($id) {
return questionnaire_get_type_name($id);
}

/**
* Return the language string for the specified question type.
* @param int $id
* @return lang_string|mixed|string
* @throws coding_exception
*/
function questionnaire_get_type_name($id) {
global $DB;

$qtypeobject = $DB->get_record('questionnaire_question_type', ['typeid' => $id], '*', MUST_EXIST);

$qtype = preg_replace("/[^a-zA-Z]+/", "", strtolower($qtypeobject->type));

$qtypeobjectnamespace = explode('\\', questionnaire_get_question_type_object($id)->fqcn)[1];

return get_string($qtype, $qtypeobjectnamespace);
}

/**
* Return the language string for all question types.
* @return array
* @throws coding_exception
*/
function questionnaire_get_all_question_types() {
global $DB;

$qtypes = $DB->get_records('questionnaire_question_type', [], 'typeid',
'typeid, type, has_choices, response_table');

foreach ($qtypes as $qtype) {
$qtypenames[$qtype->typeid] = $qtype->type;
}

return $qtypenames;
}

/**
* Return an object of the specified question type.
* @param int $id
* @return stdClass
* @throws coding_exception
*/
function questionnaire_get_question_type_object($id) {
global $DB;

$qtypeobject = $DB->get_record('questionnaire_question_type', ['typeid' => $id], '*', MUST_EXIST);

$qtype = preg_replace("/[^a-zA-Z]+/", "", strtolower($qtypeobject->type));

return $qtypeobject;
}

/**
Expand Down Expand Up @@ -876,7 +904,8 @@ function questionnaire_prep_for_questionform($questionnaire, $qid, $qtype) {
}
}
} else {
$question = \mod_questionnaire\question\question::question_builder($qtype);
$question = questionnaire_get_question_type_object($qtype);
$question = \mod_questionnaire\question\question::question_builder_fqcn($question->fqcn, $qtype);
$question->sid = $questionnaire->survey->id;
$question->id = $questionnaire->cm->id;
$question->type_id = $qtype;
Expand All @@ -890,7 +919,7 @@ function questionnaire_prep_for_questionform($questionnaire, $qid, $qtype) {
}

/**
* Get the standard page contructs and check for validity.
* Get the standard page constructs and check for validity.
* @param int $id The coursemodule id.
* @param int $a The module instance id.
* @return array An array with the $cm, $course, and $questionnaire records in that order.
Expand Down
9 changes: 5 additions & 4 deletions questionnaire.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ public function add_questions($sid = false) {
$sec = 1;
$isbreak = false;
foreach ($records as $record) {

$this->questions[$record->id] = \mod_questionnaire\question\question::question_builder($record->type_id,
$record, $this->context);
$qtypeobject = questionnaire_get_question_type_object($record->type_id);
$this->questions[$record->id] = \mod_questionnaire\question\question::question_builder_fqcn($qtypeobject->fqcn,
$record->type_id, $record, $this->context);

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

foreach ($uniquetypes as $type) {
$question = \mod_questionnaire\question\question::question_builder($type);
$qtypeobject = questionnaire_get_question_type_object($type);
$question = \mod_questionnaire\question\question::question_builder_fqcn($qtypeobject->fqcn, $type);
if (!isset($question->responsetype)) {
continue;
}
Expand Down
8 changes: 5 additions & 3 deletions questions.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@

// Log question deleted event.
$context = context_module::instance($questionnaire->cm->id);
$questiontype = \mod_questionnaire\question\question::qtypename($questionnaire->questions[$qid]->type_id);
$questiontype = questionnaire_get_all_question_types()[$questionnaire->questions[$qid]->type_id];
$params = array(
'context' => $context,
'courseid' => $questionnaire->course->id,
Expand Down Expand Up @@ -220,7 +220,8 @@
$questionrec->surveyid = $qformdata->sid;
$questionrec->type_id = QUESPAGEBREAK;
$questionrec->content = 'break';
$question = \mod_questionnaire\question\question::question_builder(QUESPAGEBREAK);
$qtypeobject = questionnaire_get_question_type_object(QUESPAGEBREAK);
$question = \mod_questionnaire\question\question::question_builder_fqcn($qtypeobject->fqcn, QUESPAGEBREAK);
$question->add($questionrec);
$reload = true;
} else {
Expand Down Expand Up @@ -296,7 +297,7 @@
// Log question created event.
if (isset($qformdata)) {
$context = context_module::instance($questionnaire->cm->id);
$questiontype = \mod_questionnaire\question\question::qtypename($qformdata->type_id);
$questiontype = questionnaire_get_all_question_types()[$qformdata->type_id];
$params = array(
'context' => $context,
'courseid' => $questionnaire->course->id,
Expand Down Expand Up @@ -413,5 +414,6 @@
} else {
$questionnaire->page->add_to_page('formarea', $questionsform->render());
}

echo $questionnaire->renderer->render($questionnaire->page);
echo $questionnaire->renderer->footer();
Loading

0 comments on commit ed117df

Please sign in to comment.