|
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 00027 defined('MOODLE_INTERNAL') || die(); 00028 00046 function get_grading_manager($context_or_areaid = null, $component = null, $area = null) { 00047 global $DB; 00048 00049 $manager = new grading_manager(); 00050 00051 if (is_object($context_or_areaid)) { 00052 $context = $context_or_areaid; 00053 } else { 00054 $context = null; 00055 00056 if (is_numeric($context_or_areaid)) { 00057 $manager->load($context_or_areaid); 00058 return $manager; 00059 } 00060 } 00061 00062 if (!is_null($context)) { 00063 $manager->set_context($context); 00064 } 00065 00066 if (!is_null($component)) { 00067 $manager->set_component($component); 00068 } 00069 00070 if (!is_null($area)) { 00071 $manager->set_area($area); 00072 } 00073 00074 return $manager; 00075 } 00076 00089 class grading_manager { 00090 00092 protected $context; 00093 00095 protected $component; 00096 00098 protected $area; 00099 00101 private $areacache = null; 00102 00106 public function get_context() { 00107 return $this->context; 00108 } 00109 00115 public function set_context(stdClass $context) { 00116 $this->areacache = null; 00117 $this->context = $context; 00118 } 00119 00123 public function get_component() { 00124 return $this->component; 00125 } 00126 00132 public function set_component($component) { 00133 $this->areacache = null; 00134 list($type, $name) = normalize_component($component); 00135 $this->component = $type.'_'.$name; 00136 } 00137 00141 public function get_area() { 00142 return $this->area; 00143 } 00144 00150 public function set_area($area) { 00151 $this->areacache = null; 00152 $this->area = $area; 00153 } 00154 00164 public function get_component_title() { 00165 00166 $this->ensure_isset(array('context', 'component')); 00167 00168 if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) { 00169 if ($this->get_component() == 'core_grading') { 00170 $title = ''; // we are in the bank UI 00171 } else { 00172 throw new coding_exception('Unsupported component at the system context'); 00173 } 00174 00175 } else if ($this->get_context()->contextlevel >= CONTEXT_COURSE) { 00176 list($context, $course, $cm) = get_context_info_array($this->get_context()->id); 00177 00178 if (!empty($cm->name)) { 00179 $title = $cm->name; 00180 } else { 00181 debugging('Gradable areas are currently supported at the course module level only', DEBUG_DEVELOPER); 00182 $title = $this->get_component(); 00183 } 00184 00185 } else { 00186 throw new coding_exception('Unsupported gradable area context level'); 00187 } 00188 00189 return $title; 00190 } 00191 00197 public function get_area_title() { 00198 00199 if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) { 00200 return ''; 00201 00202 } else if ($this->get_context()->contextlevel >= CONTEXT_COURSE) { 00203 $this->ensure_isset(array('context', 'component', 'area')); 00204 $areas = $this->get_available_areas(); 00205 if (array_key_exists($this->get_area(), $areas)) { 00206 return $areas[$this->get_area()]; 00207 } else { 00208 debugging('Unknown area!'); 00209 return '???'; 00210 } 00211 00212 } else { 00213 throw new coding_exception('Unsupported context level'); 00214 } 00215 } 00216 00222 public function load($areaid) { 00223 global $DB; 00224 00225 $this->areacache = $DB->get_record('grading_areas', array('id' => $areaid), '*', MUST_EXIST); 00226 $this->context = get_context_instance_by_id($this->areacache->contextid, MUST_EXIST); 00227 $this->component = $this->areacache->component; 00228 $this->area = $this->areacache->areaname; 00229 } 00230 00238 public static function available_methods($includenone = true) { 00239 00240 if ($includenone) { 00241 $list = array('' => get_string('gradingmethodnone', 'core_grading')); 00242 } else { 00243 $list = array(); 00244 } 00245 00246 foreach (get_plugin_list('gradingform') as $name => $location) { 00247 $list[$name] = get_string('pluginname', 'gradingform_'.$name); 00248 } 00249 00250 return $list; 00251 } 00252 00264 public function get_available_methods($includenone = true) { 00265 $this->ensure_isset(array('context')); 00266 return self::available_methods($includenone); 00267 } 00268 00278 public static function available_areas($component) { 00279 global $CFG; 00280 00281 list($plugintype, $pluginname) = normalize_component($component); 00282 00283 if ($component === 'core_grading') { 00284 return array(); 00285 00286 } else if ($plugintype === 'mod') { 00287 return plugin_callback('mod', $pluginname, 'grading', 'areas_list', null, array()); 00288 00289 } else { 00290 throw new coding_exception('Unsupported area location'); 00291 } 00292 } 00293 00294 00302 public function get_available_areas() { 00303 global $CFG; 00304 00305 $this->ensure_isset(array('context', 'component')); 00306 00307 if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) { 00308 if ($this->get_component() !== 'core_grading') { 00309 throw new coding_exception('Unsupported component at the system context'); 00310 } else { 00311 return array(); 00312 } 00313 00314 } else if ($this->get_context()->contextlevel == CONTEXT_MODULE) { 00315 list($context, $course, $cm) = get_context_info_array($this->get_context()->id); 00316 return self::available_areas('mod_'.$cm->modname); 00317 00318 } else { 00319 throw new coding_exception('Unsupported gradable area context level'); 00320 } 00321 } 00322 00328 public function get_active_method() { 00329 global $DB; 00330 00331 $this->ensure_isset(array('context', 'component', 'area')); 00332 00333 // get the current grading area record if it exists 00334 if (is_null($this->areacache)) { 00335 $this->areacache = $DB->get_record('grading_areas', array( 00336 'contextid' => $this->context->id, 00337 'component' => $this->component, 00338 'areaname' => $this->area), 00339 '*', IGNORE_MISSING); 00340 } 00341 00342 if ($this->areacache === false) { 00343 // no area record yet 00344 return null; 00345 } 00346 00347 return $this->areacache->activemethod; 00348 } 00349 00356 public function set_active_method($method) { 00357 global $DB; 00358 00359 $this->ensure_isset(array('context', 'component', 'area')); 00360 00361 // make sure the passed method is empty or a valid plugin name 00362 if (empty($method)) { 00363 $method = null; 00364 } else { 00365 if ('gradingform_'.$method !== clean_param('gradingform_'.$method, PARAM_COMPONENT)) { 00366 throw new moodle_exception('invalid_method_name', 'core_grading'); 00367 } 00368 $available = $this->get_available_methods(false); 00369 if (!array_key_exists($method, $available)) { 00370 throw new moodle_exception('invalid_method_name', 'core_grading'); 00371 } 00372 } 00373 00374 // get the current grading area record if it exists 00375 if (is_null($this->areacache)) { 00376 $this->areacache = $DB->get_record('grading_areas', array( 00377 'contextid' => $this->context->id, 00378 'component' => $this->component, 00379 'areaname' => $this->area), 00380 '*', IGNORE_MISSING); 00381 } 00382 00383 $methodchanged = false; 00384 00385 if ($this->areacache === false) { 00386 // no area record yet, create one with the active method set 00387 $area = array( 00388 'contextid' => $this->context->id, 00389 'component' => $this->component, 00390 'areaname' => $this->area, 00391 'activemethod' => $method); 00392 $DB->insert_record('grading_areas', $area); 00393 $methodchanged = true; 00394 00395 } else { 00396 // update the existing record if needed 00397 if ($this->areacache->activemethod !== $method) { 00398 $DB->set_field('grading_areas', 'activemethod', $method, array('id' => $this->areacache->id)); 00399 $methodchanged = true; 00400 } 00401 } 00402 00403 $this->areacache = null; 00404 00405 return $methodchanged; 00406 } 00407 00417 public function extend_settings_navigation(settings_navigation $settingsnav, navigation_node $modulenode=null) { 00418 00419 $this->ensure_isset(array('context', 'component')); 00420 00421 $areas = $this->get_available_areas(); 00422 00423 if (empty($areas)) { 00424 // no money, no funny 00425 return; 00426 00427 } else if (count($areas) == 1) { 00428 // make just a single node for the management screen 00429 $areatitle = reset($areas); 00430 $areaname = key($areas); 00431 $this->set_area($areaname); 00432 $method = $this->get_active_method(); 00433 $managementnode = $modulenode->add(get_string('gradingmanagement', 'core_grading'), 00434 $this->get_management_url(), settings_navigation::TYPE_CUSTOM); 00435 if ($method) { 00436 $controller = $this->get_controller($method); 00437 $controller->extend_settings_navigation($settingsnav, $managementnode); 00438 } 00439 00440 } else { 00441 // make management screen node for each area 00442 $managementnode = $modulenode->add(get_string('gradingmanagement', 'core_grading'), 00443 null, settings_navigation::TYPE_CUSTOM); 00444 foreach ($areas as $areaname => $areatitle) { 00445 $this->set_area($areaname); 00446 $method = $this->get_active_method(); 00447 $node = $managementnode->add($areatitle, 00448 $this->get_management_url(), settings_navigation::TYPE_CUSTOM); 00449 if ($method) { 00450 $controller = $this->get_controller($method); 00451 $controller->extend_settings_navigation($settingsnav, $node); 00452 } 00453 } 00454 } 00455 } 00456 00466 public function extend_navigation(global_navigation $navigation, navigation_node $modulenode=null) { 00467 $this->ensure_isset(array('context', 'component')); 00468 00469 $areas = $this->get_available_areas(); 00470 foreach ($areas as $areaname => $areatitle) { 00471 $this->set_area($areaname); 00472 if ($controller = $this->get_active_controller()) { 00473 $controller->extend_navigation($navigation, $modulenode); 00474 } 00475 } 00476 } 00477 00484 public function get_controller($method) { 00485 global $CFG, $DB; 00486 00487 $this->ensure_isset(array('context', 'component', 'area')); 00488 00489 // make sure the passed method is a valid plugin name 00490 if ('gradingform_'.$method !== clean_param('gradingform_'.$method, PARAM_COMPONENT)) { 00491 throw new moodle_exception('invalid_method_name', 'core_grading'); 00492 } 00493 $available = $this->get_available_methods(false); 00494 if (!array_key_exists($method, $available)) { 00495 throw new moodle_exception('invalid_method_name', 'core_grading'); 00496 } 00497 00498 // get the current grading area record if it exists 00499 if (is_null($this->areacache)) { 00500 $this->areacache = $DB->get_record('grading_areas', array( 00501 'contextid' => $this->context->id, 00502 'component' => $this->component, 00503 'areaname' => $this->area), 00504 '*', IGNORE_MISSING); 00505 } 00506 00507 if ($this->areacache === false) { 00508 // no area record yet, create one 00509 $area = array( 00510 'contextid' => $this->context->id, 00511 'component' => $this->component, 00512 'areaname' => $this->area); 00513 $areaid = $DB->insert_record('grading_areas', $area); 00514 // reload the cache 00515 $this->areacache = $DB->get_record('grading_areas', array('id' => $areaid), '*', MUST_EXIST); 00516 } 00517 00518 require_once($CFG->dirroot.'/grade/grading/form/'.$method.'/lib.php'); 00519 $classname = 'gradingform_'.$method.'_controller'; 00520 00521 return new $classname($this->context, $this->component, $this->area, $this->areacache->id); 00522 } 00523 00529 public function get_active_controller() { 00530 if ($gradingmethod = $this->get_active_method()) { 00531 $controller = $this->get_controller($gradingmethod); 00532 if ($controller->is_form_available()) { 00533 return $controller; 00534 } 00535 } 00536 return null; 00537 } 00538 00545 public function get_management_url(moodle_url $returnurl = null) { 00546 00547 $this->ensure_isset(array('context', 'component')); 00548 00549 if ($this->areacache) { 00550 $params = array('areaid' => $this->areacache->id); 00551 } else { 00552 $params = array('contextid' => $this->context->id, 'component' => $this->component); 00553 if ($this->area) { 00554 $params['area'] = $this->area; 00555 } 00556 } 00557 00558 if (!is_null($returnurl)) { 00559 $params['returnurl'] = $returnurl->out(false); 00560 } 00561 00562 return new moodle_url('/grade/grading/manage.php', $params); 00563 } 00564 00574 public function create_shared_area($method) { 00575 global $DB; 00576 00577 // generate some unique random name for the new area 00578 $name = $method . '_' . sha1(rand().uniqid($method, true)); 00579 // create new area record 00580 $area = array( 00581 'contextid' => context_system::instance()->id, 00582 'component' => 'core_grading', 00583 'areaname' => $name, 00584 'activemethod' => $method); 00585 return $DB->insert_record('grading_areas', $area); 00586 } 00587 00595 public static function delete_all_for_context($contextid) { 00596 global $DB; 00597 00598 $areaids = $DB->get_fieldset_select('grading_areas', 'id', 'contextid = ?', array($contextid)); 00599 $methods = array_keys(self::available_methods(false)); 00600 00601 foreach($areaids as $areaid) { 00602 $manager = get_grading_manager($areaid); 00603 foreach ($methods as $method) { 00604 $controller = $manager->get_controller($method); 00605 $controller->delete_definition(); 00606 } 00607 } 00608 00609 $DB->delete_records_list('grading_areas', 'id', $areaids); 00610 } 00611 00629 public static function tokenize($needle) { 00630 00631 // check if we are searching for the exact phrase 00632 if (preg_match('/^[\s]*"[\s]*(.*?)[\s]*"[\s]*$/', $needle, $matches)) { 00633 $token = $matches[1]; 00634 if ($token === '') { 00635 return array(); 00636 } else { 00637 return array($token); 00638 } 00639 } 00640 00641 // split the needle into smaller parts separated by non-word characters 00642 $tokens = preg_split("/\W/u", $needle); 00643 // keep just non-empty parts 00644 $tokens = array_filter($tokens); 00645 // distinct 00646 $tokens = array_unique($tokens); 00647 // drop one-letter tokens 00648 foreach ($tokens as $ix => $token) { 00649 if (strlen($token) == 1) { 00650 unset($tokens[$ix]); 00651 } 00652 } 00653 00654 return array_values($tokens); 00655 } 00656 00658 00665 private function ensure_isset(array $properties) { 00666 foreach ($properties as $property) { 00667 if (!isset($this->$property)) { 00668 throw new coding_exception('The property "'.$property.'" is not set.'); 00669 } 00670 } 00671 } 00672 }