function validation($data)
 {
     $errors = parent::validation($data, null);
     $colcount = matrix_qtype::count_form_rows_or_cols($data, false);
     $rowcount = matrix_qtype::count_form_rows_or_cols($data);
     if ($rowcount == 0) {
         $errors['rowshort[0]'] = get_string('mustdefine1by1', 'qtype_matrix');
     }
     if ($colcount == 0) {
         $errors['colshort[0]'] = get_string('mustdefine1by1', 'qtype_matrix');
     }
     if (array_key_exists('grademethod', $data)) {
         $grademethod = $data['grademethod'];
     } else {
         $grademethod = matrix_qtype::single_default_grademethod();
     }
     if ($grademethod == QTYPE_MATRIX_GRADING_WEIGHTED && empty($data['multiple'])) {
         $errors['multiple'] = get_string('weightednomultiple', 'qtype_matrix');
     }
     $gradeclass = matrix_qtype::grade_class($grademethod, $data['multiple']);
     $matrixerrors = $gradeclass->validate_defining_form_matrix($data);
     $errors = array_merge($errors, $matrixerrors);
     return $errors ? $errors : true;
 }
 /**
  * Save the units and the answers associated with this question.
  * @return boolean to indicate success of failure.
  */
 function save_question_options($question)
 {
     $existingdata = self::load_all_data($question->id);
     if (!empty($question->makecopy)) {
         $existingdata = false;
     }
     begin_sql();
     $matrix = (object) array('questionid' => $question->id, 'multiple' => $question->multiple, 'grademethod' => $question->grademethod, 'renderer' => 'matrix');
     if (!$existingdata) {
         $matrixid = insert_record('question_matrix', $matrix);
     } else {
         $matrix->id = $matrixid = $existingdata->id;
         update_record('question_matrix', $matrix);
     }
     $rowcoltemplate = array('matrixid' => $matrixid);
     $rowids = array();
     // mapping for indexes to db ids.
     $colids = array();
     $newrowcount = QTYPE_MATRIX_NEWHEADER_STARTCOUNT;
     $newcolcount = QTYPE_MATRIX_NEWHEADER_STARTCOUNT;
     $colcount = matrix_qtype::count_form_rows_or_cols((array) $question, false);
     $rowcount = matrix_qtype::count_form_rows_or_cols((array) $question);
     // rows
     for ($i = 0; $i < $rowcount; $i++) {
         $row = (object) array_merge($rowcoltemplate, array('shorttext' => $question->rowshort[$i], 'description' => aget($question->rowlong, $i, ''), 'feedback' => $question->rowfeedback[$i], 'id' => @$question->rowid[$i]));
         if (!$existingdata || !array_key_exists($row->id, $existingdata->rows)) {
             $oldid = $row->id;
             unset($row->id);
             $newid = insert_record('question_matrix_rows', $row);
             if (!empty($oldid)) {
                 // this happens when we copy a question
                 $rowids[$oldid] = $newid;
             } else {
                 $rowids[$newrowcount] = $newid;
                 $newrowcount++;
             }
         } else {
             if (array_key_exists($row->id, $existingdata->rows)) {
                 $rowids[$row->id] = $row->id;
                 update_record('question_matrix_rows', $row);
             }
         }
     }
     // cols
     for ($i = 0; $i < $colcount; $i++) {
         $col = (object) array_merge($rowcoltemplate, array('shorttext' => $question->colshort[$i], 'description' => $question->collong[$i], 'id' => @$question->colid[$i]));
         if (!$existingdata || !array_key_exists($col->id, $existingdata->cols)) {
             $oldid = $col->id;
             unset($col->id);
             $newid = insert_record('question_matrix_cols', $col);
             if (!empty($oldid)) {
                 $colids[$oldid] = $newid;
             } else {
                 $colids[$newcolcount] = $newid;
                 $newcolcount++;
             }
         } else {
             if (array_key_exists($col->id, $existingdata->cols)) {
                 $colids[$col->id] = $col->id;
                 update_record('question_matrix_cols', $col);
             }
         }
     }
     $matrix = self::formdata_to_matrix((array) $question);
     $gradeclass = matrix_qtype::grade_class($question->grademethod, $question->multiple);
     $percents = $gradeclass->store_percentages();
     global $CFG;
     delete_records_select('question_matrix_weights', 'rowid IN (
                 SELECT id FROM ' . $CFG->prefix . 'question_matrix_rows
                 WHERE matrixid = ' . $matrixid . ')
             OR colid IN (
                 SELECT id FROM ' . $CFG->prefix . 'question_matrix_cols
                 WHERE matrixid = ' . $matrixid . ')');
     foreach ($matrix as $r => $row) {
         foreach ($row as $c => $cell) {
             if (empty($cell)) {
                 continue;
             }
             $weight = (object) array('rowid' => $rowids[$r], 'colid' => $colids[$c], 'weight' => $percents ? $cell : '1');
             insert_record('question_matrix_weights', $weight);
         }
     }
     if ($rowids) {
         delete_records_select('question_matrix_rows', 'matrixid = ' . $matrixid . ' AND id NOT IN (' . implode(',', $rowids) . ')');
     }
     if ($colids) {
         delete_records_select('question_matrix_cols', 'matrixid = ' . $matrixid . ' AND id NOT IN (' . implode(',', $colids) . ')');
     }
     return commit_sql();
 }