[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/grade/grading/form/guide/ -> guideeditor.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   * This file contains the marking guide editor element
  19   *
  20   * @package    gradingform_guide
  21   * @copyright  2012 Dan Marsden <[email protected]>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  require_once("HTML/QuickForm/input.php");
  28  
  29  /**
  30   * The editor for the marking guide advanced grading plugin.
  31   *
  32   * @package    gradingform_guide
  33   * @copyright  2012 Dan Marsden <[email protected]>
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class moodlequickform_guideeditor extends HTML_QuickForm_input {
  37      /** @var string help message */
  38      public $_helpbutton = '';
  39      /** @var null|false|string stores the result of the last validation: null - undefined, false - no errors,
  40       * string - error(s) text */
  41      protected $validationerrors = null;
  42      /** @var bool if element has already been validated **/
  43      protected $wasvalidated = false;
  44      /** @var null|bool If non-submit (JS) button was pressed: null - unknown, true/false - button was/wasn't pressed */
  45      protected $nonjsbuttonpressed = false;
  46      /** @var string|false Message to display in front of the editor (that there exist grades on this guide being edited) */
  47      protected $regradeconfirmation = false;
  48  
  49      /**
  50       * Constructor
  51       *
  52       * @param string $elementname
  53       * @param string $elementlabel
  54       * @param array $attributes
  55       */
  56      public function moodlequickform_guideeditor($elementname=null, $elementlabel=null, $attributes=null) {
  57          parent::HTML_QuickForm_input($elementname, $elementlabel, $attributes);
  58      }
  59  
  60      /**
  61       * get html for help button
  62       *
  63       * @return  string html for help button
  64       */
  65      public function getHelpButton() {
  66          return $this->_helpbutton;
  67      }
  68  
  69      /**
  70       * The renderer will take care itself about different display in normal and frozen states
  71       *
  72       * @return string
  73       */
  74      public function getElementTemplateType() {
  75          return 'default';
  76      }
  77  
  78      /**
  79       * Specifies that confirmation about re-grading needs to be added to this rubric editor.
  80       * $changelevel is saved in $this->regradeconfirmation and retrieved in toHtml()
  81       *
  82       * @see gradingform_rubric_controller::update_or_check_rubric()
  83       * @param int $changelevel
  84       */
  85      public function add_regrade_confirmation($changelevel) {
  86          $this->regradeconfirmation = $changelevel;
  87      }
  88  
  89      /**
  90       * Returns html string to display this element
  91       *
  92       * @return string
  93       */
  94      public function toHtml() {
  95          global $PAGE;
  96          $html = $this->_getTabs();
  97          $renderer = $PAGE->get_renderer('gradingform_guide');
  98          $data = $this->prepare_data(null, $this->wasvalidated);
  99          if (!$this->_flagFrozen) {
 100              $mode = gradingform_guide_controller::DISPLAY_EDIT_FULL;
 101              $module = array('name'=>'gradingform_guideeditor',
 102                  'fullpath'=>'/grade/grading/form/guide/js/guideeditor.js',
 103                  'requires' => array('base', 'dom', 'event', 'event-touch', 'escape'),
 104                  'strings' => array(
 105                      array('confirmdeletecriterion', 'gradingform_guide'),
 106                      array('clicktoedit', 'gradingform_guide'),
 107                      array('clicktoeditname', 'gradingform_guide')
 108              ));
 109              $PAGE->requires->js_init_call('M.gradingform_guideeditor.init', array(
 110                  array('name' => $this->getName(),
 111                      'criteriontemplate' => $renderer->criterion_template($mode, $data['options'], $this->getName()),
 112                      'commenttemplate' => $renderer->comment_template($mode, $this->getName())
 113                     )),
 114                  true, $module);
 115          } else {
 116              // Guide is frozen, no javascript needed.
 117              if ($this->_persistantFreeze) {
 118                  $mode = gradingform_guide_controller::DISPLAY_EDIT_FROZEN;
 119              } else {
 120                  $mode = gradingform_guide_controller::DISPLAY_PREVIEW;
 121              }
 122          }
 123          if ($this->regradeconfirmation) {
 124              if (!isset($data['regrade'])) {
 125                  $data['regrade'] = 1;
 126              }
 127              $html .= $renderer->display_regrade_confirmation($this->getName(), $this->regradeconfirmation, $data['regrade']);
 128          }
 129          if ($this->validationerrors) {
 130              $html .= $renderer->notification($this->validationerrors, 'error');
 131          }
 132          $html .= $renderer->display_guide($data['criteria'], $data['comments'], $data['options'], $mode, $this->getName());
 133          return $html;
 134      }
 135      /**
 136       * Prepares the data passed in $_POST:
 137       * - processes the pressed buttons 'addlevel', 'addcriterion', 'moveup', 'movedown', 'delete' (when JavaScript is disabled)
 138       *   sets $this->nonjsbuttonpressed to true/false if such button was pressed
 139       * - if options not passed (i.e. we create a new guide) fills the options array with the default values
 140       * - if options are passed completes the options array with unchecked checkboxes
 141       * - if $withvalidation is set, adds 'error_xxx' attributes to elements that contain errors and creates an error string
 142       *   and stores it in $this->validationerrors
 143       *
 144       * @param array $value
 145       * @param boolean $withvalidation whether to enable data validation
 146       * @return array
 147       */
 148      protected function prepare_data($value = null, $withvalidation = false) {
 149          if (null === $value) {
 150              $value = $this->getValue();
 151          }
 152          if ($this->nonjsbuttonpressed === null) {
 153              $this->nonjsbuttonpressed = false;
 154          }
 155  
 156          $errors = array();
 157          $return = array('criteria' => array(), 'options' => gradingform_guide_controller::get_default_options(),
 158              'comments' => array());
 159          if (!isset($value['criteria'])) {
 160              $value['criteria'] = array();
 161              $errors['err_nocriteria'] = 1;
 162          }
 163          // If options are present in $value, replace default values with submitted values.
 164          if (!empty($value['options'])) {
 165              foreach (array_keys($return['options']) as $option) {
 166                  // Special treatment for checkboxes.
 167                  if (!empty($value['options'][$option])) {
 168                      $return['options'][$option] = $value['options'][$option];
 169                  } else {
 170                      $return['options'][$option] = null;
 171                  }
 172  
 173              }
 174          }
 175  
 176          if (is_array($value)) {
 177              // For other array keys of $value no special treatmeant neeeded, copy them to return value as is.
 178              foreach (array_keys($value) as $key) {
 179                  if ($key != 'options' && $key != 'criteria' && $key != 'comments') {
 180                      $return[$key] = $value[$key];
 181                  }
 182              }
 183          }
 184  
 185          // Iterate through criteria.
 186          $lastaction = null;
 187          $lastid = null;
 188          foreach ($value['criteria'] as $id => $criterion) {
 189              if ($id == 'addcriterion') {
 190                  $id = $this->get_next_id(array_keys($value['criteria']));
 191                  $criterion = array('description' => '');
 192                  $this->nonjsbuttonpressed = true;
 193              }
 194  
 195              if ($withvalidation && !array_key_exists('delete', $criterion)) {
 196                  if (!strlen(trim($criterion['shortname']))) {
 197                      $errors['err_noshortname'] = 1;
 198                      $criterion['error_description'] = true;
 199                  }
 200                  if (!strlen(trim($criterion['maxscore']))) {
 201                      $errors['err_nomaxscore'] = 1;
 202                      $criterion['error_description'] = true;
 203                  } else if (!is_numeric($criterion['maxscore']) || $criterion['maxscore'] < 0) {
 204                      $errors['err_maxscorenotnumeric'] = 1;
 205                      $criterion['error_description'] = true;
 206                  }
 207              }
 208              if (array_key_exists('moveup', $criterion) || $lastaction == 'movedown') {
 209                  unset($criterion['moveup']);
 210                  if ($lastid !== null) {
 211                      $lastcriterion = $return['criteria'][$lastid];
 212                      unset($return['criteria'][$lastid]);
 213                      $return['criteria'][$id] = $criterion;
 214                      $return['criteria'][$lastid] = $lastcriterion;
 215                  } else {
 216                      $return['criteria'][$id] = $criterion;
 217                  }
 218                  $lastaction = null;
 219                  $lastid = $id;
 220                  $this->nonjsbuttonpressed = true;
 221              } else if (array_key_exists('delete', $criterion)) {
 222                  $this->nonjsbuttonpressed = true;
 223              } else {
 224                  if (array_key_exists('movedown', $criterion)) {
 225                      unset($criterion['movedown']);
 226                      $lastaction = 'movedown';
 227                      $this->nonjsbuttonpressed = true;
 228                  }
 229                  $return['criteria'][$id] = $criterion;
 230                  $lastid = $id;
 231              }
 232          }
 233  
 234          // Add sort order field to criteria.
 235          $csortorder = 1;
 236          foreach (array_keys($return['criteria']) as $id) {
 237              $return['criteria'][$id]['sortorder'] = $csortorder++;
 238          }
 239  
 240          // Iterate through comments.
 241          $lastaction = null;
 242          $lastid = null;
 243          if (!empty($value['comments'])) {
 244              foreach ($value['comments'] as $id => $comment) {
 245                  if ($id == 'addcomment') {
 246                      $id = $this->get_next_id(array_keys($value['comments']));
 247                      $comment = array('description' => '');
 248                      $this->nonjsbuttonpressed = true;
 249                  }
 250  
 251                  if (array_key_exists('moveup', $comment) || $lastaction == 'movedown') {
 252                      unset($comment['moveup']);
 253                      if ($lastid !== null) {
 254                          $lastcomment = $return['comments'][$lastid];
 255                          unset($return['comments'][$lastid]);
 256                          $return['comments'][$id] = $comment;
 257                          $return['comments'][$lastid] = $lastcomment;
 258                      } else {
 259                          $return['comments'][$id] = $comment;
 260                      }
 261                      $lastaction = null;
 262                      $lastid = $id;
 263                      $this->nonjsbuttonpressed = true;
 264                  } else if (array_key_exists('delete', $comment)) {
 265                      $this->nonjsbuttonpressed = true;
 266                  } else {
 267                      if (array_key_exists('movedown', $comment)) {
 268                          unset($comment['movedown']);
 269                          $lastaction = 'movedown';
 270                          $this->nonjsbuttonpressed = true;
 271                      }
 272                      $return['comments'][$id] = $comment;
 273                      $lastid = $id;
 274                  }
 275              }
 276              // Add sort order field to comments.
 277              $csortorder = 1;
 278              foreach (array_keys($return['comments']) as $id) {
 279                  $return['comments'][$id]['sortorder'] = $csortorder++;
 280              }
 281          }
 282          // Create validation error string (if needed).
 283          if ($withvalidation) {
 284              if (count($errors)) {
 285                  $rv = array();
 286                  foreach ($errors as $error => $v) {
 287                      $rv[] = get_string($error, 'gradingform_guide');
 288                  }
 289                  $this->validationerrors = join('<br/ >', $rv);
 290              } else {
 291                  $this->validationerrors = false;
 292              }
 293              $this->wasvalidated = true;
 294          }
 295          return $return;
 296  
 297      }
 298  
 299      /**
 300       * Scans array $ids to find the biggest element ! NEWID*, increments it by 1 and returns
 301       *
 302       * @param array $ids
 303       * @return string
 304       */
 305      protected function get_next_id($ids) {
 306          $maxid = 0;
 307          foreach ($ids as $id) {
 308              if (preg_match('/^NEWID(\d+)$/', $id, $matches) && ((int)$matches[1]) > $maxid) {
 309                  $maxid = (int)$matches[1];
 310              }
 311          }
 312          return 'NEWID'.($maxid+1);
 313      }
 314  
 315      /**
 316       * Checks if a submit button was pressed which is supposed to be processed on client side by JS
 317       * but user seem to have disabled JS in the browser.
 318       * (buttons 'add criteria', 'add level', 'move up', 'move down', 'add comment')
 319       * In this case the form containing this element is prevented from being submitted
 320       *
 321       * @param array $value
 322       * @return boolean true if non-submit button was pressed and not processed by JS
 323       */
 324      public function non_js_button_pressed($value) {
 325          if ($this->nonjsbuttonpressed === null) {
 326              $this->prepare_data($value);
 327          }
 328          return $this->nonjsbuttonpressed;
 329      }
 330  
 331      /**
 332       * Validates that guide has at least one criterion, filled definitions and all criteria
 333       * have filled descriptions
 334       *
 335       * @param array $value
 336       * @return string|false error text or false if no errors found
 337       */
 338      public function validate($value) {
 339          if (!$this->wasvalidated) {
 340              $this->prepare_data($value, true);
 341          }
 342          return $this->validationerrors;
 343      }
 344  
 345      /**
 346       * Prepares the data for saving
 347       * @see prepare_data()
 348       *
 349       * @param array $submitvalues
 350       * @param boolean $assoc
 351       * @return array
 352       */
 353      public function exportValue(&$submitvalues, $assoc = false) {
 354          $value =  $this->prepare_data($this->_findValue($submitvalues));
 355          return $this->_prepareValue($value, $assoc);
 356      }
 357  }


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