[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Advanced role definition form. 19 * 20 * @package core_role 21 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 28 /** 29 * As well as tracking the permissions information about the role we are creating 30 * or editing, we also track the other information about the role. (This class is 31 * starting to be more and more like a formslib form in some respects.) 32 */ 33 class core_role_define_role_table_advanced extends core_role_capability_table_with_risks { 34 /** @var stdClass Used to store other information (besides permissions) about the role we are creating/editing. */ 35 protected $role; 36 /** @var array Used to store errors found when validating the data. */ 37 protected $errors; 38 protected $contextlevels; 39 protected $allcontextlevels; 40 protected $disabled = ''; 41 42 protected $allowassign; 43 protected $allowoverride; 44 protected $allowswitch; 45 46 public function __construct($context, $roleid) { 47 $this->roleid = $roleid; 48 parent::__construct($context, 'defineroletable', $roleid); 49 $this->displaypermissions = $this->allpermissions; 50 $this->strperms[$this->allpermissions[CAP_INHERIT]] = get_string('notset', 'core_role'); 51 52 $this->allcontextlevels = array(); 53 $levels = context_helper::get_all_levels(); 54 foreach ($levels as $level => $classname) { 55 $this->allcontextlevels[$level] = context_helper::get_level_name($level); 56 } 57 } 58 59 protected function load_current_permissions() { 60 global $DB; 61 if ($this->roleid) { 62 if (!$this->role = $DB->get_record('role', array('id' => $this->roleid))) { 63 throw new moodle_exception('invalidroleid'); 64 } 65 $contextlevels = get_role_contextlevels($this->roleid); 66 // Put the contextlevels in the array keys, as well as the values. 67 if (!empty($contextlevels)) { 68 $this->contextlevels = array_combine($contextlevels, $contextlevels); 69 } else { 70 $this->contextlevels = array(); 71 } 72 $this->allowassign = array_keys($this->get_allow_roles_list('assign')); 73 $this->allowoverride = array_keys($this->get_allow_roles_list('override')); 74 $this->allowswitch = array_keys($this->get_allow_roles_list('switch')); 75 76 } else { 77 $this->role = new stdClass; 78 $this->role->name = ''; 79 $this->role->shortname = ''; 80 $this->role->description = ''; 81 $this->role->archetype = ''; 82 $this->contextlevels = array(); 83 $this->allowassign = array(); 84 $this->allowoverride = array(); 85 $this->allowswitch = array(); 86 } 87 parent::load_current_permissions(); 88 } 89 90 public function read_submitted_permissions() { 91 global $DB; 92 $this->errors = array(); 93 94 // Role short name. We clean this in a special way. We want to end up 95 // with only lowercase safe ASCII characters. 96 $shortname = optional_param('shortname', null, PARAM_RAW); 97 if (!is_null($shortname)) { 98 $this->role->shortname = $shortname; 99 $this->role->shortname = core_text::specialtoascii($this->role->shortname); 100 $this->role->shortname = core_text::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT)); 101 if (empty($this->role->shortname)) { 102 $this->errors['shortname'] = get_string('errorbadroleshortname', 'core_role'); 103 } 104 } 105 if ($DB->record_exists_select('role', 'shortname = ? and id <> ?', array($this->role->shortname, $this->roleid))) { 106 $this->errors['shortname'] = get_string('errorexistsroleshortname', 'core_role'); 107 } 108 109 // Role name. 110 $name = optional_param('name', null, PARAM_TEXT); 111 if (!is_null($name)) { 112 $this->role->name = $name; 113 // Hack: short names of standard roles are equal to archetypes, empty name means localised via lang packs. 114 $archetypes = get_role_archetypes(); 115 if (!isset($archetypes[$shortname]) and html_is_blank($this->role->name)) { 116 $this->errors['name'] = get_string('errorbadrolename', 'core_role'); 117 } 118 } 119 if ($this->role->name !== '' and $DB->record_exists_select('role', 'name = ? and id <> ?', array($this->role->name, $this->roleid))) { 120 $this->errors['name'] = get_string('errorexistsrolename', 'core_role'); 121 } 122 123 // Description. 124 $description = optional_param('description', null, PARAM_RAW); 125 if (!is_null($description)) { 126 $this->role->description = $description; 127 } 128 129 // Legacy type. 130 $archetype = optional_param('archetype', null, PARAM_RAW); 131 if (isset($archetype)) { 132 $archetypes = get_role_archetypes(); 133 if (isset($archetypes[$archetype])) { 134 $this->role->archetype = $archetype; 135 } else { 136 $this->role->archetype = ''; 137 } 138 } 139 140 // Assignable context levels. 141 foreach ($this->allcontextlevels as $cl => $notused) { 142 $assignable = optional_param('contextlevel' . $cl, null, PARAM_BOOL); 143 if (!is_null($assignable)) { 144 if ($assignable) { 145 $this->contextlevels[$cl] = $cl; 146 } else { 147 unset($this->contextlevels[$cl]); 148 } 149 } 150 } 151 152 // Allowed roles. 153 $allow = optional_param_array('allowassign', null, PARAM_INT); 154 if (!is_null($allow)) { 155 $this->allowassign = $allow; 156 } 157 $allow = optional_param_array('allowoverride', null, PARAM_INT); 158 if (!is_null($allow)) { 159 $this->allowoverride = $allow; 160 } 161 $allow = optional_param_array('allowswitch', null, PARAM_INT); 162 if (!is_null($allow)) { 163 $this->allowswitch = $allow; 164 } 165 166 // Now read the permissions for each capability. 167 parent::read_submitted_permissions(); 168 } 169 170 public function is_submission_valid() { 171 return empty($this->errors); 172 } 173 174 /** 175 * Call this after the table has been initialised, 176 * this resets everything to that role. 177 * 178 * @param int $roleid role id or 0 for no role 179 * @param array $options array with following keys: 180 * 'name', 'shortname', 'description', 'permissions', 'archetype', 181 * 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch' 182 */ 183 public function force_duplicate($roleid, array $options) { 184 global $DB; 185 186 if ($roleid == 0) { 187 // This means reset to nothing == remove everything. 188 189 if ($options['shortname']) { 190 $this->role->shortname = ''; 191 } 192 193 if ($options['name']) { 194 $this->role->name = ''; 195 } 196 197 if ($options['description']) { 198 $this->role->description = ''; 199 } 200 201 if ($options['archetype']) { 202 $this->role->archetype = ''; 203 } 204 205 if ($options['contextlevels']) { 206 $this->contextlevels = array(); 207 } 208 209 if ($options['allowassign']) { 210 $this->allowassign = array(); 211 } 212 if ($options['allowoverride']) { 213 $this->allowoverride = array(); 214 } 215 if ($options['allowswitch']) { 216 $this->allowswitch = array(); 217 } 218 219 if ($options['permissions']) { 220 foreach ($this->capabilities as $capid => $cap) { 221 $this->permissions[$cap->name] = CAP_INHERIT; 222 } 223 } 224 225 return; 226 } 227 228 $role = $DB->get_record('role', array('id'=>$roleid), '*', MUST_EXIST); 229 230 if ($options['shortname']) { 231 $this->role->shortname = $role->shortname; 232 } 233 234 if ($options['name']) { 235 $this->role->name = $role->name; 236 } 237 238 if ($options['description']) { 239 $this->role->description = $role->description; 240 } 241 242 if ($options['archetype']) { 243 $this->role->archetype = $role->archetype; 244 } 245 246 if ($options['contextlevels']) { 247 $this->contextlevels = array(); 248 $levels = get_role_contextlevels($roleid); 249 foreach ($levels as $cl) { 250 $this->contextlevels[$cl] = $cl; 251 } 252 } 253 254 if ($options['allowassign']) { 255 $this->allowassign = array_keys($this->get_allow_roles_list('assign', $roleid)); 256 } 257 if ($options['allowoverride']) { 258 $this->allowoverride = array_keys($this->get_allow_roles_list('override', $roleid)); 259 } 260 if ($options['allowswitch']) { 261 $this->allowswitch = array_keys($this->get_allow_roles_list('switch', $roleid)); 262 } 263 264 if ($options['permissions']) { 265 $this->permissions = $DB->get_records_menu('role_capabilities', 266 array('roleid' => $roleid, 'contextid' => context_system::instance()->id), 267 '', 'capability,permission'); 268 269 foreach ($this->capabilities as $capid => $cap) { 270 if (!isset($this->permissions[$cap->name])) { 271 $this->permissions[$cap->name] = CAP_INHERIT; 272 } 273 } 274 } 275 } 276 277 /** 278 * Change the role definition to match given archetype. 279 * 280 * @param string $archetype 281 * @param array $options array with following keys: 282 * 'name', 'shortname', 'description', 'permissions', 'archetype', 283 * 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch' 284 */ 285 public function force_archetype($archetype, array $options) { 286 $archetypes = get_role_archetypes(); 287 if (!isset($archetypes[$archetype])) { 288 throw new coding_exception('Unknown archetype: '.$archetype); 289 } 290 291 if ($options['shortname']) { 292 $this->role->shortname = ''; 293 } 294 295 if ($options['name']) { 296 $this->role->name = ''; 297 } 298 299 if ($options['description']) { 300 $this->role->description = ''; 301 } 302 303 if ($options['archetype']) { 304 $this->role->archetype = $archetype; 305 } 306 307 if ($options['contextlevels']) { 308 $this->contextlevels = array(); 309 $defaults = get_default_contextlevels($archetype); 310 foreach ($defaults as $cl) { 311 $this->contextlevels[$cl] = $cl; 312 } 313 } 314 315 if ($options['allowassign']) { 316 $this->allowassign = get_default_role_archetype_allows('assign', $archetype); 317 } 318 if ($options['allowoverride']) { 319 $this->allowoverride = get_default_role_archetype_allows('override', $archetype); 320 } 321 if ($options['allowswitch']) { 322 $this->allowswitch = get_default_role_archetype_allows('switch', $archetype); 323 } 324 325 if ($options['permissions']) { 326 $defaultpermissions = get_default_capabilities($archetype); 327 foreach ($this->permissions as $k => $v) { 328 if (isset($defaultpermissions[$k])) { 329 $this->permissions[$k] = $defaultpermissions[$k]; 330 continue; 331 } 332 $this->permissions[$k] = CAP_INHERIT; 333 } 334 } 335 } 336 337 /** 338 * Change the role definition to match given preset. 339 * 340 * @param string $xml 341 * @param array $options array with following keys: 342 * 'name', 'shortname', 'description', 'permissions', 'archetype', 343 * 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch' 344 */ 345 public function force_preset($xml, array $options) { 346 if (!$info = core_role_preset::parse_preset($xml)) { 347 throw new coding_exception('Invalid role preset'); 348 } 349 350 if ($options['shortname']) { 351 if (isset($info['shortname'])) { 352 $this->role->shortname = $info['shortname']; 353 } 354 } 355 356 if ($options['name']) { 357 if (isset($info['name'])) { 358 $this->role->name = $info['name']; 359 } 360 } 361 362 if ($options['description']) { 363 if (isset($info['description'])) { 364 $this->role->description = $info['description']; 365 } 366 } 367 368 if ($options['archetype']) { 369 if (isset($info['archetype'])) { 370 $this->role->archetype = $info['archetype']; 371 } 372 } 373 374 if ($options['contextlevels']) { 375 if (isset($info['contextlevels'])) { 376 $this->contextlevels = $info['contextlevels']; 377 } 378 } 379 380 foreach (array('assign', 'override', 'switch') as $type) { 381 if ($options['allow'.$type]) { 382 if (isset($info['allow'.$type])) { 383 $this->{'allow'.$type} = $info['allow'.$type]; 384 } 385 } 386 } 387 388 if ($options['permissions']) { 389 foreach ($this->permissions as $k => $v) { 390 // Note: do not set everything else to CAP_INHERIT here 391 // because the xml file might not contain all capabilities. 392 if (isset($info['permissions'][$k])) { 393 $this->permissions[$k] = $info['permissions'][$k]; 394 } 395 } 396 } 397 } 398 399 public function get_role_name() { 400 return $this->role->name; 401 } 402 403 public function get_role_id() { 404 return $this->role->id; 405 } 406 407 public function get_archetype() { 408 return $this->role->archetype; 409 } 410 411 protected function load_parent_permissions() { 412 $this->parentpermissions = get_default_capabilities($this->role->archetype); 413 } 414 415 public function save_changes() { 416 global $DB; 417 418 if (!$this->roleid) { 419 // Creating role. 420 $this->role->id = create_role($this->role->name, $this->role->shortname, $this->role->description, $this->role->archetype); 421 $this->roleid = $this->role->id; // Needed to make the parent::save_changes(); call work. 422 } else { 423 // Updating role. 424 $DB->update_record('role', $this->role); 425 } 426 427 // Assignable contexts. 428 set_role_contextlevels($this->role->id, $this->contextlevels); 429 430 // Set allowed roles. 431 $this->save_allow('assign'); 432 $this->save_allow('override'); 433 $this->save_allow('switch'); 434 435 // Permissions. 436 parent::save_changes(); 437 } 438 439 protected function save_allow($type) { 440 global $DB; 441 442 $current = array_keys($this->get_allow_roles_list($type)); 443 $wanted = $this->{'allow'.$type}; 444 445 $addfunction = 'allow_'.$type; 446 $deltable = 'role_allow_'.$type; 447 $field = 'allow'.$type; 448 449 foreach ($current as $roleid) { 450 if (!in_array($roleid, $wanted)) { 451 $DB->delete_records($deltable, array('roleid'=>$this->roleid, $field=>$roleid)); 452 continue; 453 } 454 $key = array_search($roleid, $wanted); 455 unset($wanted[$key]); 456 } 457 458 foreach ($wanted as $roleid) { 459 if ($roleid == -1) { 460 $roleid = $this->roleid; 461 } 462 $addfunction($this->roleid, $roleid); 463 } 464 } 465 466 protected function get_name_field($id) { 467 return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->name) . '" />'; 468 } 469 470 protected function get_shortname_field($id) { 471 return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->shortname) . '" />'; 472 } 473 474 protected function get_description_field($id) { 475 return print_textarea(true, 10, 50, 50, 10, 'description', $this->role->description, 0, true); 476 } 477 478 protected function get_archetype_field($id) { 479 $options = array(); 480 $options[''] = get_string('none'); 481 foreach (get_role_archetypes() as $type) { 482 $options[$type] = get_string('archetype'.$type, 'role'); 483 } 484 return html_writer::select($options, 'archetype', $this->role->archetype, false); 485 } 486 487 protected function get_assignable_levels_control() { 488 $output = ''; 489 foreach ($this->allcontextlevels as $cl => $clname) { 490 $extraarguments = $this->disabled; 491 if (in_array($cl, $this->contextlevels)) { 492 $extraarguments .= 'checked="checked" '; 493 } 494 if (!$this->disabled) { 495 $output .= '<input type="hidden" name="contextlevel' . $cl . '" value="0" />'; 496 } 497 $output .= '<input type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl . 498 '" value="1" ' . $extraarguments . '/> '; 499 $output .= '<label for="cl' . $cl . '">' . $clname . "</label><br />\n"; 500 } 501 return $output; 502 } 503 504 /** 505 * Returns an array of roles of the allowed type. 506 * 507 * @param string $type Must be one of: assign, switch, or override. 508 * @param int $roleid (null means current role) 509 * @return array 510 */ 511 protected function get_allow_roles_list($type, $roleid = null) { 512 global $DB; 513 514 if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') { 515 debugging('Invalid role allowed type specified', DEBUG_DEVELOPER); 516 return array(); 517 } 518 519 if ($roleid === null) { 520 $roleid = $this->roleid; 521 } 522 523 if (empty($roleid)) { 524 return array(); 525 } 526 527 $sql = "SELECT r.* 528 FROM {role} r 529 JOIN {role_allow_{$type}} a ON a.allow{$type} = r.id 530 WHERE a.roleid = :roleid 531 ORDER BY r.sortorder ASC"; 532 return $DB->get_records_sql($sql, array('roleid'=>$roleid)); 533 } 534 535 /** 536 * Returns an array of roles with the allowed type. 537 * 538 * @param string $type Must be one of: assign, switch, or override. 539 * @return array Am array of role names with the allowed type 540 */ 541 protected function get_allow_role_control($type) { 542 if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') { 543 debugging('Invalid role allowed type specified', DEBUG_DEVELOPER); 544 return ''; 545 } 546 547 $property = 'allow'.$type; 548 $selected = $this->$property; 549 550 $options = array(); 551 foreach (role_get_names(null, ROLENAME_ALIAS) as $role) { 552 $options[$role->id] = $role->localname; 553 } 554 if ($this->roleid == 0) { 555 $options[-1] = get_string('thisnewrole', 'core_role'); 556 } 557 return html_writer::select($options, 'allow'.$type.'[]', $selected, false, array('multiple'=>'multiple', 'size'=>10)); 558 } 559 560 /** 561 * Returns information about the risks associated with a role. 562 * 563 * @return string 564 */ 565 protected function get_role_risks_info() { 566 return ''; 567 } 568 569 protected function print_field($name, $caption, $field) { 570 global $OUTPUT; 571 // Attempt to generate HTML like formslib. 572 echo '<div class="fitem">'; 573 echo '<div class="fitemtitle">'; 574 if ($name) { 575 echo '<label for="' . $name . '">'; 576 } 577 echo $caption; 578 if ($name) { 579 echo "</label>\n"; 580 } 581 echo '</div>'; 582 if (isset($this->errors[$name])) { 583 $extraclass = ' error'; 584 } else { 585 $extraclass = ''; 586 } 587 echo '<div class="felement' . $extraclass . '">'; 588 echo $field; 589 if (isset($this->errors[$name])) { 590 echo $OUTPUT->error_text($this->errors[$name]); 591 } 592 echo '</div>'; 593 echo '</div>'; 594 } 595 596 protected function print_show_hide_advanced_button() { 597 echo '<p class="definenotice">' . get_string('highlightedcellsshowdefault', 'core_role') . ' </p>'; 598 echo '<div class="advancedbutton">'; 599 echo '<input type="submit" name="toggleadvanced" value="' . get_string('hideadvanced', 'form') . '" />'; 600 echo '</div>'; 601 } 602 603 public function display() { 604 global $OUTPUT; 605 // Extra fields at the top of the page. 606 echo '<div class="topfields clearfix">'; 607 $this->print_field('shortname', get_string('roleshortname', 'core_role').' '.$OUTPUT->help_icon('roleshortname', 'core_role'), $this->get_shortname_field('shortname')); 608 $this->print_field('name', get_string('customrolename', 'core_role').' '.$OUTPUT->help_icon('customrolename', 'core_role'), $this->get_name_field('name')); 609 $this->print_field('edit-description', get_string('customroledescription', 'core_role').' '.$OUTPUT->help_icon('customroledescription', 'core_role'), 610 $this->get_description_field('description')); 611 $this->print_field('menuarchetype', get_string('archetype', 'core_role').' '.$OUTPUT->help_icon('archetype', 'core_role'), $this->get_archetype_field('archetype')); 612 $this->print_field('', get_string('maybeassignedin', 'core_role'), $this->get_assignable_levels_control()); 613 $this->print_field('menuallowassign', get_string('allowassign', 'core_role'), $this->get_allow_role_control('assign')); 614 $this->print_field('menuallowoverride', get_string('allowoverride', 'core_role'), $this->get_allow_role_control('override')); 615 $this->print_field('menuallowswitch', get_string('allowswitch', 'core_role'), $this->get_allow_role_control('switch')); 616 if ($risks = $this->get_role_risks_info()) { 617 $this->print_field('', get_string('rolerisks', 'core_role'), $risks); 618 } 619 echo "</div>"; 620 621 $this->print_show_hide_advanced_button(); 622 623 // Now the permissions table. 624 parent::display(); 625 } 626 627 protected function add_permission_cells($capability) { 628 // One cell for each possible permission. 629 foreach ($this->displaypermissions as $perm => $permname) { 630 $strperm = $this->strperms[$permname]; 631 $extraclass = ''; 632 if ($perm == $this->parentpermissions[$capability->name]) { 633 $extraclass = ' capdefault'; 634 } 635 $checked = ''; 636 if ($this->permissions[$capability->name] == $perm) { 637 $checked = 'checked="checked" '; 638 } 639 echo '<td class="' . $permname . $extraclass . '">'; 640 echo '<label><input type="radio" name="' . $capability->name . 641 '" value="' . $perm . '" ' . $checked . '/> '; 642 echo '<span class="note">' . $strperm . '</span>'; 643 echo '</label></td>'; 644 } 645 } 646 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |