|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00025 defined('MOODLE_INTERNAL') || die(); 00026 00027 require_once("HTML/QuickForm/input.php"); 00028 00029 class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { 00031 public $_helpbutton = ''; 00033 protected $validationerrors = null; 00035 protected $wasvalidated = false; 00037 protected $nonjsbuttonpressed = false; 00039 protected $regradeconfirmation = false; 00040 00041 function MoodleQuickForm_rubriceditor($elementName=null, $elementLabel=null, $attributes=null) { 00042 parent::HTML_QuickForm_input($elementName, $elementLabel, $attributes); 00043 } 00044 00052 public function setHelpButton($helpbuttonargs, $function='helpbutton'){ 00053 debugging('component setHelpButton() is not used any more, please use $mform->setHelpButton() instead'); 00054 } 00055 00062 public function getHelpButton() { 00063 return $this->_helpbutton; 00064 } 00065 00071 public function getElementTemplateType() { 00072 return 'default'; 00073 } 00074 00082 public function add_regrade_confirmation($changelevel) { 00083 $this->regradeconfirmation = $changelevel; 00084 } 00085 00091 public function toHtml() { 00092 global $PAGE; 00093 $html = $this->_getTabs(); 00094 $renderer = $PAGE->get_renderer('gradingform_rubric'); 00095 $data = $this->prepare_data(null, $this->wasvalidated); 00096 if (!$this->_flagFrozen) { 00097 $mode = gradingform_rubric_controller::DISPLAY_EDIT_FULL; 00098 $module = array('name'=>'gradingform_rubriceditor', 'fullpath'=>'/grade/grading/form/rubric/js/rubriceditor.js', 00099 'strings' => array(array('confirmdeletecriterion', 'gradingform_rubric'), array('confirmdeletelevel', 'gradingform_rubric'), 00100 array('criterionempty', 'gradingform_rubric'), array('levelempty', 'gradingform_rubric') 00101 )); 00102 $PAGE->requires->js_init_call('M.gradingform_rubriceditor.init', array( 00103 array('name' => $this->getName(), 00104 'criteriontemplate' => $renderer->criterion_template($mode, $data['options'], $this->getName()), 00105 'leveltemplate' => $renderer->level_template($mode, $data['options'], $this->getName()) 00106 )), 00107 true, $module); 00108 } else { 00109 // Rubric is frozen, no javascript needed 00110 if ($this->_persistantFreeze) { 00111 $mode = gradingform_rubric_controller::DISPLAY_EDIT_FROZEN; 00112 } else { 00113 $mode = gradingform_rubric_controller::DISPLAY_PREVIEW; 00114 } 00115 } 00116 if ($this->regradeconfirmation) { 00117 if (!isset($data['regrade'])) { 00118 $data['regrade'] = 1; 00119 } 00120 $html .= $renderer->display_regrade_confirmation($this->getName(), $this->regradeconfirmation, $data['regrade']); 00121 } 00122 if ($this->validationerrors) { 00123 $html .= $renderer->notification($this->validationerrors, 'error'); 00124 } 00125 $html .= $renderer->display_rubric($data['criteria'], $data['options'], $mode, $this->getName()); 00126 return $html; 00127 } 00128 00142 protected function prepare_data($value = null, $withvalidation = false) { 00143 if (null === $value) { 00144 $value = $this->getValue(); 00145 } 00146 if ($this->nonjsbuttonpressed === null) { 00147 $this->nonjsbuttonpressed = false; 00148 } 00149 $totalscore = 0; 00150 $errors = array(); 00151 $return = array('criteria' => array(), 'options' => gradingform_rubric_controller::get_default_options()); 00152 if (!isset($value['criteria'])) { 00153 $value['criteria'] = array(); 00154 $errors['err_nocriteria'] = 1; 00155 } 00156 // If options are present in $value, replace default values with submitted values 00157 if (!empty($value['options'])) { 00158 foreach (array_keys($return['options']) as $option) { 00159 // special treatment for checkboxes 00160 if (!empty($value['options'][$option])) { 00161 $return['options'][$option] = $value['options'][$option]; 00162 } else { 00163 $return['options'][$option] = null; 00164 } 00165 } 00166 } 00167 if (is_array($value)) { 00168 // for other array keys of $value no special treatmeant neeeded, copy them to return value as is 00169 foreach (array_keys($value) as $key) { 00170 if ($key != 'options' && $key != 'criteria') { 00171 $return[$key] = $value[$key]; 00172 } 00173 } 00174 } 00175 00176 // iterate through criteria 00177 $lastaction = null; 00178 $lastid = null; 00179 foreach ($value['criteria'] as $id => $criterion) { 00180 if ($id == 'addcriterion') { 00181 $id = $this->get_next_id(array_keys($value['criteria'])); 00182 $criterion = array('description' => '', 'levels' => array()); 00183 $i = 0; 00184 // when adding new criterion copy the number of levels and their scores from the last criterion 00185 if (!empty($value['criteria'][$lastid]['levels'])) { 00186 foreach ($value['criteria'][$lastid]['levels'] as $lastlevel) { 00187 $criterion['levels']['NEWID'.($i++)]['score'] = $lastlevel['score']; 00188 } 00189 } else { 00190 $criterion['levels']['NEWID'.($i++)]['score'] = 0; 00191 } 00192 // add more levels so there are at least 3 in the new criterion. Increment by 1 the score for each next one 00193 for ($i=$i; $i<3; $i++) { 00194 $criterion['levels']['NEWID'.$i]['score'] = $criterion['levels']['NEWID'.($i-1)]['score'] + 1; 00195 } 00196 // set other necessary fields (definition) for the levels in the new criterion 00197 foreach (array_keys($criterion['levels']) as $i) { 00198 $criterion['levels'][$i]['definition'] = ''; 00199 } 00200 $this->nonjsbuttonpressed = true; 00201 } 00202 $levels = array(); 00203 $maxscore = null; 00204 if (array_key_exists('levels', $criterion)) { 00205 foreach ($criterion['levels'] as $levelid => $level) { 00206 if ($levelid == 'addlevel') { 00207 $levelid = $this->get_next_id(array_keys($criterion['levels'])); 00208 $level = array( 00209 'definition' => '', 00210 'score' => 0, 00211 ); 00212 foreach ($criterion['levels'] as $lastlevel) { 00213 if ($level['score'] < $lastlevel['score'] + 1) { 00214 $level['score'] = $lastlevel['score'] + 1; 00215 } 00216 } 00217 $this->nonjsbuttonpressed = true; 00218 } 00219 if (!array_key_exists('delete', $level)) { 00220 if ($withvalidation) { 00221 if (!strlen(trim($level['definition']))) { 00222 $errors['err_nodefinition'] = 1; 00223 $level['error_definition'] = true; 00224 } 00225 if (!preg_match('#^[\+]?\d*$#', trim($level['score'])) && !preg_match('#^[\+]?\d*[\.,]\d+$#', trim($level['score']))) { 00226 // TODO why we can't allow negative score for rubric? 00227 $errors['err_scoreformat'] = 1; 00228 $level['error_score'] = true; 00229 } 00230 } 00231 $levels[$levelid] = $level; 00232 if ($maxscore === null || (float)$level['score'] > $maxscore) { 00233 $maxscore = (float)$level['score']; 00234 } 00235 } else { 00236 $this->nonjsbuttonpressed = true; 00237 } 00238 } 00239 } 00240 $totalscore += (float)$maxscore; 00241 $criterion['levels'] = $levels; 00242 if ($withvalidation && !array_key_exists('delete', $criterion)) { 00243 if (count($levels)<2) { 00244 $errors['err_mintwolevels'] = 1; 00245 $criterion['error_levels'] = true; 00246 } 00247 if (!strlen(trim($criterion['description']))) { 00248 $errors['err_nodescription'] = 1; 00249 $criterion['error_description'] = true; 00250 } 00251 } 00252 if (array_key_exists('moveup', $criterion) || $lastaction == 'movedown') { 00253 unset($criterion['moveup']); 00254 if ($lastid !== null) { 00255 $lastcriterion = $return['criteria'][$lastid]; 00256 unset($return['criteria'][$lastid]); 00257 $return['criteria'][$id] = $criterion; 00258 $return['criteria'][$lastid] = $lastcriterion; 00259 } else { 00260 $return['criteria'][$id] = $criterion; 00261 } 00262 $lastaction = null; 00263 $lastid = $id; 00264 $this->nonjsbuttonpressed = true; 00265 } else if (array_key_exists('delete', $criterion)) { 00266 $this->nonjsbuttonpressed = true; 00267 } else { 00268 if (array_key_exists('movedown', $criterion)) { 00269 unset($criterion['movedown']); 00270 $lastaction = 'movedown'; 00271 $this->nonjsbuttonpressed = true; 00272 } 00273 $return['criteria'][$id] = $criterion; 00274 $lastid = $id; 00275 } 00276 } 00277 00278 if ($totalscore <= 0) { 00279 $errors['err_totalscore'] = 1; 00280 } 00281 00282 // add sort order field to criteria 00283 $csortorder = 1; 00284 foreach (array_keys($return['criteria']) as $id) { 00285 $return['criteria'][$id]['sortorder'] = $csortorder++; 00286 } 00287 00288 // create validation error string (if needed) 00289 if ($withvalidation) { 00290 if (count($errors)) { 00291 $rv = array(); 00292 foreach ($errors as $error => $v) { 00293 $rv[] = get_string($error, 'gradingform_rubric'); 00294 } 00295 $this->validationerrors = join('<br/ >', $rv); 00296 } else { 00297 $this->validationerrors = false; 00298 } 00299 $this->wasvalidated = true; 00300 } 00301 return $return; 00302 } 00303 00310 protected function get_next_id($ids) { 00311 $maxid = 0; 00312 foreach ($ids as $id) { 00313 if (preg_match('/^NEWID(\d+)$/', $id, $matches) && ((int)$matches[1]) > $maxid) { 00314 $maxid = (int)$matches[1]; 00315 } 00316 } 00317 return 'NEWID'.($maxid+1); 00318 } 00319 00329 public function non_js_button_pressed($value) { 00330 if ($this->nonjsbuttonpressed === null) { 00331 $this->prepare_data($value); 00332 } 00333 return $this->nonjsbuttonpressed; 00334 } 00335 00344 public function validate($value) { 00345 if (!$this->wasvalidated) { 00346 $this->prepare_data($value, true); 00347 } 00348 return $this->validationerrors; 00349 } 00350 00359 public function exportValue(&$submitValues, $assoc = false) { 00360 $value = $this->prepare_data($this->_findValue($submitValues)); 00361 return $this->_prepareValue($value, $assoc); 00362 } 00363 }