[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/admin/roles/classes/ -> define_role_table_advanced.php (source)

   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').'&nbsp;'.$OUTPUT->help_icon('roleshortname', 'core_role'), $this->get_shortname_field('shortname'));
 608          $this->print_field('name', get_string('customrolename', 'core_role').'&nbsp;'.$OUTPUT->help_icon('customrolename', 'core_role'), $this->get_name_field('name'));
 609          $this->print_field('edit-description', get_string('customroledescription', 'core_role').'&nbsp;'.$OUTPUT->help_icon('customroledescription', 'core_role'),
 610              $this->get_description_field('description'));
 611          $this->print_field('menuarchetype', get_string('archetype', 'core_role').'&nbsp;'.$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  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1