/**
  * Check question's form data for valid response. Override this is type has specific format requirements.
  *
  * @param object $responsedata The data entered into the response.
  * @return boolean
  */
 public function response_valid($responsedata)
 {
     if (isset($responsedata->{'q' . $this->id})) {
         $checkdateresult = '';
         if ($responsedata->{'q' . $this->id} != '') {
             $checkdateresult = questionnaire_check_date($responsedata->{'q' . $this->id});
         }
         return substr($checkdateresult, 0, 5) != 'wrong';
     } else {
         return parent::response_valid($responsedata);
     }
 }
 public function insert_response($rid, $val)
 {
     global $DB;
     $checkdateresult = questionnaire_check_date($val);
     $thisdate = $val;
     if (substr($checkdateresult, 0, 5) == 'wrong') {
         return false;
     }
     // Now use ISO date formatting.
     $checkdateresult = questionnaire_check_date($thisdate, true);
     $record = new \stdClass();
     $record->response_id = $rid;
     $record->question_id = $this->question->id;
     $record->response = $checkdateresult;
     return $DB->insert_record($this->response_table(), $record);
 }
 private function response_check_format($section, &$formdata, $qnum = '')
 {
     global $PAGE, $OUTPUT;
     $missing = 0;
     $strmissing = '';
     // Missing questions.
     $wrongformat = 0;
     $strwrongformat = '';
     // Wrongly formatted questions (Numeric, 5:Check Boxes, Date).
     $i = 1;
     for ($j = 2; $j <= $section; $j++) {
         // ADDED A SIMPLE LOOP FOR MAKING SURE PAGE BREAKS (type 99) AND LABELS (type 100) ARE NOT ALLOWED.
         foreach ($this->questionsbysec[$j - 1] as $sectionrecord) {
             $tid = $sectionrecord->type_id;
             if ($tid < QUESPAGEBREAK) {
                 $i++;
             }
         }
     }
     $qnum = $i - 1;
     foreach ($this->questionsbysec[$section] as $question) {
         $qid = $question->id;
         $tid = $question->type_id;
         $lid = $question->length;
         $pid = $question->precise;
         if ($tid != QUESSECTIONTEXT) {
             $qnum++;
         }
         $missingresp = false;
         // Note: The "missing response" detection is carried out differently in Rate questions (see below).
         if ($question->required == 'y' && $question->deleted == 'n' && (isset($formdata->{'q' . $qid}) && $formdata->{'q' . $qid} == '' || !isset($formdata->{'q' . $qid})) && $tid != QUESSECTIONTEXT && $tid != QUESRATE) {
             if ($PAGE->pagetype != 'mod-questionnaire-preview') {
                 $missingresp = true;
             } else {
                 if ($question->dependquestion == 0) {
                     $missingresp = true;
                 } else {
                     // For yes/no questions, convert 0 and 1 to y(es) and n(o).
                     if ($question->dependchoice == 0) {
                         $dependchoice = 'y';
                     } else {
                         if ($question->dependchoice == 1) {
                             $dependchoice = 'n';
                         } else {
                             $dependchoice = $question->dependchoice;
                         }
                     }
                     if (isset($formdata->{'q' . $question->dependquestion}) && $formdata->{'q' . $question->dependquestion} == $dependchoice) {
                         $missingresp = true;
                     }
                 }
             }
         }
         if ($missingresp) {
             $missing++;
             $strmissing .= get_string('num', 'questionnaire') . $qnum . '. ';
         }
         switch ($tid) {
             case QUESRADIO:
                 // Radio Buttons with !other field.
                 if (!isset($formdata->{'q' . $qid})) {
                     break;
                 }
                 $resp = $formdata->{'q' . $qid};
                 $pos = strpos($resp, 'other_');
                 // Other "other" choice is checked but text box is empty.
                 if (is_int($pos) == true) {
                     $othercontent = "q" . $qid . substr($resp, 5);
                     if (!$formdata->{$othercontent}) {
                         $wrongformat++;
                         $strwrongformat .= get_string('num', 'questionnaire') . $qnum . '. ';
                         break;
                     }
                 }
                 if (is_int($pos) == true && $question->required == 'y') {
                     $resp = 'q' . $qid . '' . substr($resp, 5);
                     if (!$formdata->{$resp}) {
                         $missing++;
                         $strmissing .= get_string('num', 'questionnaire') . $qnum . '. ';
                     }
                 }
                 break;
             case QUESCHECK:
                 // Check Boxes.
                 if (!isset($formdata->{'q' . $qid})) {
                     break;
                 }
                 $resps = $formdata->{'q' . $qid};
                 $nbrespchoices = 0;
                 foreach ($resps as $resp) {
                     $pos = strpos($resp, 'other_');
                     // Other "other" choice is checked but text box is empty.
                     if (is_int($pos) == true) {
                         $othercontent = "q" . $qid . substr($resp, 5);
                         if (!$formdata->{$othercontent}) {
                             $wrongformat++;
                             $strwrongformat .= get_string('num', 'questionnaire') . $qnum . '. ';
                             break;
                         }
                     }
                     if (is_numeric($resp) || is_int($pos) == true) {
                         $nbrespchoices++;
                     }
                 }
                 $nbquestchoices = count($question->choices);
                 $min = $lid;
                 $max = $pid;
                 if ($max == 0) {
                     $max = $nbquestchoices;
                 }
                 if ($min > $max) {
                     $min = $max;
                     // Sanity check.
                 }
                 $min = min($nbquestchoices, $min);
                 // Number of ticked boxes is not within min and max set limits.
                 if ($nbrespchoices && ($nbrespchoices < $min || $nbrespchoices > $max)) {
                     $wrongformat++;
                     $strwrongformat .= get_string('num', 'questionnaire') . $qnum . '. ';
                     break;
                 }
                 break;
             case QUESRATE:
                 // Rate.
                 $num = 0;
                 $nbchoices = count($question->choices);
                 $na = get_string('notapplicable', 'questionnaire');
                 foreach ($question->choices as $cid => $choice) {
                     // In case we have named degrees on the Likert scale, count them to substract from nbchoices.
                     $nameddegrees = 0;
                     $content = $choice->content;
                     if (preg_match("/^[0-9]{1,3}=/", $content, $ndd)) {
                         $nameddegrees++;
                     } else {
                         $str = 'q' . "{$question->id}_{$cid}";
                         if (isset($formdata->{$str}) && $formdata->{$str} == $na) {
                             $formdata->{$str} = -1;
                         }
                         for ($j = 0; $j < $question->length; $j++) {
                             $num += isset($formdata->{$str}) && $j == $formdata->{$str};
                         }
                         $num += $question->precise && isset($formdata->{$str}) && $formdata->{$str} == -1;
                     }
                     $nbchoices -= $nameddegrees;
                 }
                 if ($num == 0) {
                     $missingresp = false;
                     if ($PAGE->pagetype != 'mod-questionnaire-preview' || $question->dependquestion == 0) {
                         if ($question->required == 'y') {
                             $missingresp = true;
                         }
                     } else {
                         if (isset($formdata->{'q' . $question->dependquestion}) && $formdata->{'q' . $question->dependquestion} == $question->dependchoice) {
                             $missingresp = true;
                         }
                     }
                     if ($missingresp) {
                         $missing++;
                         $strmissing .= get_string('num', 'questionnaire') . $qnum . '. ';
                     }
                 }
                 // If nodupes and nb choice restricted, nbchoices may be > actual choices, so limit it to $question->length.
                 $isrestricted = $question->length < count($question->choices) && $question->precise == 2;
                 if ($isrestricted) {
                     $nbchoices = min($nbchoices, $question->length);
                 }
                 if ($num != $nbchoices && $num != 0) {
                     $wrongformat++;
                     $strwrongformat .= get_string('num', 'questionnaire') . $qnum . '. ';
                 }
                 break;
             case QUESDATE:
                 // Date.
                 if (!isset($formdata->{'q' . $qid})) {
                     break;
                 }
                 $checkdateresult = '';
                 if ($formdata->{'q' . $qid} != '') {
                     $checkdateresult = questionnaire_check_date($formdata->{'q' . $qid});
                 }
                 if (substr($checkdateresult, 0, 5) == 'wrong') {
                     $wrongformat++;
                     $strwrongformat .= get_string('num', 'questionnaire') . $qnum . '. ';
                 }
                 break;
             case QUESNUMERIC:
                 // Numeric.
                 if (!isset($formdata->{'q' . $qid})) {
                     break;
                 }
                 if ($formdata->{'q' . $qid} != '' && !is_numeric($formdata->{'q' . $qid})) {
                     $wrongformat++;
                     $strwrongformat .= get_string('num', 'questionnaire') . $qnum . '. ';
                 }
                 break;
             default:
                 break;
         }
     }
     $message = '';
     $nonumbering = false;
     $autonum = $this->autonum;
     // If no questions autonumbering do not display missing question(s) number(s).
     if ($autonum != 1 && $autonum != 3) {
         $nonumbering = true;
     }
     if ($missing) {
         if ($nonumbering) {
             $strmissing = '';
         }
         if ($missing == 1) {
             $message = get_string('missingquestion', 'questionnaire') . $strmissing;
         } else {
             $message = get_string('missingquestions', 'questionnaire') . $strmissing;
         }
         if ($wrongformat) {
             $message .= '<br />';
         }
     }
     if ($wrongformat) {
         if ($nonumbering) {
             $message .= get_string('wronganswers', 'questionnaire');
         } else {
             if ($wrongformat == 1) {
                 $message .= get_string('wrongformat', 'questionnaire') . $strwrongformat;
             } else {
                 $message .= get_string('wrongformats', 'questionnaire') . $strwrongformat;
             }
         }
     }
     return $message;
 }
 private function date_survey_display($data)
 {
     // Date.
     $datemess = html_writer::start_tag('div', array('class' => 'qn-datemsg'));
     $datemess .= get_string('dateformatting', 'questionnaire');
     $datemess .= html_writer::end_tag('div');
     if (!empty($data->{'q' . $this->id})) {
         $dateentered = $data->{'q' . $this->id};
         $setdate = questionnaire_check_date($dateentered, false);
         if ($setdate == 'wrongdateformat') {
             $msg = get_string('wrongdateformat', 'questionnaire', $dateentered);
             questionnaire_notify($msg);
         } else {
             if ($setdate == 'wrongdaterange') {
                 $msg = get_string('wrongdaterange', 'questionnaire');
                 questionnaire_notify($msg);
             } else {
                 $data->{'q' . $this->id} = $setdate;
             }
         }
     }
     echo $datemess;
     echo html_writer::start_tag('div', array('class' => 'qn-date'));
     echo '<input onkeypress="return event.keyCode != 13;" type="text" size="12" name="q' . $this->id . '" maxlength="10" value="' . (isset($data->{'q' . $this->id}) ? $data->{'q' . $this->id} : '') . '" />';
     echo html_writer::end_tag('div');
 }