[ Index ] |
PHP Cross Reference of Unnamed Project |
[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 * Contains class mod_feedback_complete_form 19 * 20 * @package mod_feedback 21 * @copyright 2016 Marina Glancy 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 /** 28 * Class mod_feedback_complete_form 29 * 30 * @package mod_feedback 31 * @copyright 2016 Marina Glancy 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class mod_feedback_complete_form extends moodleform { 35 36 /** @var int */ 37 const MODE_COMPLETE = 1; 38 /** @var int */ 39 const MODE_PRINT = 2; 40 /** @var int */ 41 const MODE_EDIT = 3; 42 /** @var int */ 43 const MODE_VIEW_RESPONSE = 4; 44 /** @var int */ 45 const MODE_VIEW_TEMPLATE = 5; 46 47 /** @var int */ 48 protected $mode; 49 /** @var mod_feedback_structure|mod_feedback_completion */ 50 protected $structure; 51 /** @var mod_feedback_completion */ 52 protected $completion; 53 /** @var int */ 54 protected $gopage; 55 /** @var bool */ 56 protected $hasrequired = false; 57 58 /** 59 * Constructor 60 * 61 * @param int $mode 62 * @param mod_feedback_structure $structure 63 * @param string $formid CSS id attribute of the form 64 * @param array $customdata 65 */ 66 public function __construct($mode, mod_feedback_structure $structure, $formid, $customdata = null) { 67 $this->mode = $mode; 68 $this->structure = $structure; 69 $this->gopage = isset($customdata['gopage']) ? $customdata['gopage'] : 0; 70 $isanonymous = $this->structure->is_anonymous() ? ' ianonymous' : ''; 71 parent::__construct(null, $customdata, 'POST', '', 72 array('id' => $formid, 'class' => 'feedback_form' . $isanonymous), true); 73 } 74 75 /** 76 * Form definition 77 */ 78 public function definition() { 79 $mform = $this->_form; 80 $mform->addElement('hidden', 'id', $this->get_cm()->id); 81 $mform->setType('id', PARAM_INT); 82 $mform->addElement('hidden', 'courseid', $this->get_current_course_id()); 83 $mform->setType('courseid', PARAM_INT); 84 $mform->addElement('hidden', 'gopage'); 85 $mform->setType('gopage', PARAM_INT); 86 $mform->addElement('hidden', 'lastpage'); 87 $mform->setType('lastpage', PARAM_INT); 88 $mform->addElement('hidden', 'startitempos'); 89 $mform->setType('startitempos', PARAM_INT); 90 $mform->addElement('hidden', 'lastitempos'); 91 $mform->setType('lastitempos', PARAM_INT); 92 93 if (isloggedin() && !isguestuser() && $this->mode != self::MODE_EDIT && $this->mode != self::MODE_VIEW_TEMPLATE && 94 $this->mode != self::MODE_VIEW_RESPONSE) { 95 // Output information about the current mode (anonymous or not) in some modes. 96 if ($this->structure->is_anonymous()) { 97 $anonymousmodeinfo = get_string('anonymous', 'feedback'); 98 } else { 99 $anonymousmodeinfo = get_string('non_anonymous', 'feedback'); 100 } 101 $element = $mform->addElement('static', 'anonymousmode', '', 102 get_string('mode', 'feedback') . ': ' . $anonymousmodeinfo); 103 $element->setAttributes($element->getAttributes() + ['class' => 'feedback_mode']); 104 } 105 106 // Add buttons to go to previous/next pages and submit the feedback. 107 if ($this->mode == self::MODE_COMPLETE) { 108 $buttonarray = array(); 109 $buttonarray[] = &$mform->createElement('submit', 'gopreviouspage', get_string('previous_page', 'feedback')); 110 $buttonarray[] = &$mform->createElement('submit', 'gonextpage', get_string('next_page', 'feedback'), 111 array('class' => 'form-submit')); 112 $buttonarray[] = &$mform->createElement('submit', 'savevalues', get_string('save_entries', 'feedback'), 113 array('class' => 'form-submit')); 114 $buttonarray[] = &$mform->createElement('static', 'buttonsseparator', '', '<br>'); 115 $buttonarray[] = &$mform->createElement('cancel'); 116 $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); 117 $mform->closeHeaderBefore('buttonar'); 118 } 119 120 if ($this->mode == self::MODE_COMPLETE) { 121 $this->definition_complete(); 122 } else { 123 $this->definition_preview(); 124 } 125 126 // Set data. 127 $this->set_data(array('gopage' => $this->gopage)); 128 } 129 130 /** 131 * Called from definition_after_data() in the completion mode 132 * 133 * This will add only items from a current page to the feedback and adjust the buttons 134 */ 135 protected function definition_complete() { 136 if (!$this->structure instanceof mod_feedback_completion) { 137 // We should not really be here but just in case. 138 return; 139 } 140 $pages = $this->structure->get_pages(); 141 $gopage = $this->gopage; 142 $pageitems = $pages[$gopage]; 143 $hasnextpage = $gopage < count($pages) - 1; // Until we complete this page we can not trust get_next_page(). 144 $hasprevpage = $gopage && ($this->structure->get_previous_page($gopage, false) !== null); 145 146 // Add elements. 147 foreach ($pageitems as $item) { 148 $itemobj = feedback_get_item_class($item->typ); 149 $itemobj->complete_form_element($item, $this); 150 } 151 152 // Remove invalid buttons (for example, no "previous page" if we are on the first page). 153 if (!$hasprevpage) { 154 $this->remove_button('gopreviouspage'); 155 } 156 if (!$hasnextpage) { 157 $this->remove_button('gonextpage'); 158 } 159 if ($hasnextpage) { 160 $this->remove_button('savevalues'); 161 } 162 } 163 164 /** 165 * Called from definition_after_data() in all modes except for completion 166 * 167 * This will add all items to the form, including pagebreaks as horizontal rules. 168 */ 169 protected function definition_preview() { 170 foreach ($this->structure->get_items() as $feedbackitem) { 171 $itemobj = feedback_get_item_class($feedbackitem->typ); 172 $itemobj->complete_form_element($feedbackitem, $this); 173 } 174 } 175 176 /** 177 * Removes the button that is not applicable for the current page 178 * 179 * @param string $buttonname 180 */ 181 private function remove_button($buttonname) { 182 $el = $this->_form->getElement('buttonar'); 183 foreach ($el->_elements as $idx => $button) { 184 if ($button instanceof MoodleQuickForm_submit && $button->getName() === $buttonname) { 185 unset($el->_elements[$idx]); 186 return; 187 } 188 } 189 } 190 191 /** 192 * Returns value for this element that is already stored in temporary or permanent table, 193 * usually only available when user clicked "Previous page". Null means no value is stored. 194 * 195 * @param stdClass $item 196 * @return string 197 */ 198 public function get_item_value($item) { 199 if ($this->structure instanceof mod_feedback_completion) { 200 return $this->structure->get_item_value($item); 201 } 202 return null; 203 } 204 205 /** 206 * Can be used by the items to get the course id for which feedback is taken 207 * 208 * This function returns 0 for feedbacks that are located inside the courses. 209 * $this->get_feedback()->course will return the course where feedback is located. 210 * $this->get_current_course_id() will return the course where user was before taking the feedback 211 * 212 * @return int 213 */ 214 public function get_course_id() { 215 return $this->structure->get_courseid(); 216 } 217 218 /** 219 * Record from 'feedback' table corresponding to the current feedback 220 * @return stdClass 221 */ 222 public function get_feedback() { 223 return $this->structure->get_feedback(); 224 } 225 226 /** 227 * Current feedback mode, see constants on the top of this class 228 * @return int 229 */ 230 public function get_mode() { 231 return $this->mode; 232 } 233 234 /** 235 * Returns whether the form is frozen, some items may prefer to change the element 236 * type in case of frozen form. For example, text or textarea element does not look 237 * nice when frozen 238 * 239 * @return bool 240 */ 241 public function is_frozen() { 242 return $this->mode == self::MODE_VIEW_RESPONSE; 243 } 244 245 /** 246 * Returns the current course module 247 * @return cm_info 248 */ 249 public function get_cm() { 250 return $this->structure->get_cm(); 251 } 252 253 /** 254 * Returns the course where user was before taking the feedback. 255 * 256 * For feedbacks inside the course it will be the same as $this->get_feedback()->course. 257 * For feedbacks on the frontpage it will be the same as $this->get_course_id() 258 * 259 * @return int 260 */ 261 public function get_current_course_id() { 262 return $this->structure->get_courseid() ?: $this->get_feedback()->course; 263 } 264 265 /** 266 * CSS class for the item 267 * @param stdClass $item 268 * @return string 269 */ 270 protected function get_suggested_class($item) { 271 $class = "feedback_itemlist feedback-item-{$item->typ}"; 272 if ($item->dependitem) { 273 $class .= " feedback_is_dependent"; 274 } 275 if ($item->typ !== 'pagebreak') { 276 $itemobj = feedback_get_item_class($item->typ); 277 if ($itemobj->get_hasvalue()) { 278 $class .= " feedback_hasvalue"; 279 } 280 } 281 return $class; 282 } 283 284 /** 285 * Adds an element to this form - to be used by items in their complete_form_element() method 286 * 287 * @param stdClass $item 288 * @param HTML_QuickForm_element|array $element either completed form element or an array that 289 * can be passed as arguments to $this->_form->createElement() function 290 * @param bool $addrequiredrule automatically add 'required' rule 291 * @param bool $setdefaultvalue automatically set default value for element 292 * @return HTML_QuickForm_element 293 */ 294 public function add_form_element($item, $element, $addrequiredrule = true, $setdefaultvalue = true) { 295 global $OUTPUT; 296 // Add element to the form. 297 if (is_array($element)) { 298 if ($this->is_frozen() && $element[0] === 'text') { 299 // Convert 'text' element to 'static' when freezing for better display. 300 $element = ['static', $element[1], $element[2]]; 301 } 302 $element = call_user_func_array(array($this->_form, 'createElement'), $element); 303 } 304 $element = $this->_form->addElement($element); 305 306 // Prepend standard CSS classes to the element classes. 307 $attributes = $element->getAttributes(); 308 $class = !empty($attributes['class']) ? ' ' . $attributes['class'] : ''; 309 $attributes['class'] = $this->get_suggested_class($item) . $class; 310 $element->setAttributes($attributes); 311 312 // Add required rule. 313 if ($item->required && $addrequiredrule) { 314 $this->_form->addRule($element->getName(), get_string('required'), 'required', null, 'client'); 315 } 316 317 // Set default value. 318 if ($setdefaultvalue && ($tmpvalue = $this->get_item_value($item))) { 319 $this->_form->setDefault($element->getName(), $tmpvalue); 320 } 321 322 // Freeze if needed. 323 if ($this->is_frozen()) { 324 $element->freeze(); 325 } 326 327 // Add red asterisks on required fields. 328 if ($item->required) { 329 $required = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'. 330 get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />'; 331 $element->setLabel($element->getLabel() . $required); 332 $this->hasrequired = true; 333 } 334 335 // Add different useful stuff to the question name. 336 $this->add_item_label($item, $element); 337 $this->add_item_dependencies($item, $element); 338 $this->add_item_number($item, $element); 339 340 if ($this->mode == self::MODE_EDIT) { 341 $this->enhance_name_for_edit($item, $element); 342 } 343 344 return $element; 345 } 346 347 /** 348 * Adds a group element to this form - to be used by items in their complete_form_element() method 349 * 350 * @param stdClass $item 351 * @param string $groupinputname name for the form element 352 * @param string $name question text 353 * @param array $elements array of arrays that can be passed to $this->_form->createElement() 354 * @param string $separator separator between group elements 355 * @param string $class additional CSS classes for the form element 356 * @return HTML_QuickForm_element 357 */ 358 public function add_form_group_element($item, $groupinputname, $name, $elements, $separator, 359 $class = '') { 360 $objects = array(); 361 foreach ($elements as $element) { 362 $object = call_user_func_array(array($this->_form, 'createElement'), $element); 363 $objects[] = $object; 364 } 365 $element = $this->add_form_element($item, 366 ['group', $groupinputname, $name, $objects, $separator, false], 367 false, 368 false); 369 if ($class !== '') { 370 $attributes = $element->getAttributes(); 371 $attributes['class'] .= ' ' . $class; 372 $element->setAttributes($attributes); 373 } 374 return $element; 375 } 376 377 /** 378 * Adds an item number to the question name (if feedback autonumbering is on) 379 * @param stdClass $item 380 * @param HTML_QuickForm_element $element 381 */ 382 protected function add_item_number($item, $element) { 383 if ($this->get_feedback()->autonumbering && !empty($item->itemnr)) { 384 $name = $element->getLabel(); 385 $element->setLabel(html_writer::span($item->itemnr. '.', 'itemnr') . ' ' . $name); 386 } 387 } 388 389 /** 390 * Adds an item label to the question name 391 * @param stdClass $item 392 * @param HTML_QuickForm_element $element 393 */ 394 protected function add_item_label($item, $element) { 395 if (strlen($item->label) && ($this->mode == self::MODE_EDIT || $this->mode == self::MODE_VIEW_TEMPLATE)) { 396 $name = $element->getLabel(); 397 $name = '('.format_string($item->label).') '.$name; 398 $element->setLabel($name); 399 } 400 } 401 402 /** 403 * Adds a dependency description to the question name 404 * @param stdClass $item 405 * @param HTML_QuickForm_element $element 406 */ 407 protected function add_item_dependencies($item, $element) { 408 $allitems = $this->structure->get_items(); 409 if ($item->dependitem && ($this->mode == self::MODE_EDIT || $this->mode == self::MODE_VIEW_TEMPLATE)) { 410 if (isset($allitems[$item->dependitem])) { 411 $dependitem = $allitems[$item->dependitem]; 412 $name = $element->getLabel(); 413 $name .= html_writer::span(' ('.format_string($dependitem->label).'->'.$item->dependvalue.')', 414 'feedback_depend'); 415 $element->setLabel($name); 416 } 417 } 418 } 419 420 /** 421 * Returns the CSS id attribute that will be assigned by moodleform later to this element 422 * @param stdClass $item 423 * @param HTML_QuickForm_element $element 424 */ 425 protected function guess_element_id($item, $element) { 426 if (!$id = $element->getAttribute('id')) { 427 $attributes = $element->getAttributes(); 428 $id = $attributes['id'] = 'feedback_item_' . $item->id; 429 $element->setAttributes($attributes); 430 } 431 if ($element->getType() === 'group') { 432 return 'fgroup_' . $id; 433 } 434 return 'fitem_' . $id; 435 } 436 437 /** 438 * Adds editing actions to the question name in the edit mode 439 * @param stdClass $item 440 * @param HTML_QuickForm_element $element 441 */ 442 protected function enhance_name_for_edit($item, $element) { 443 global $OUTPUT; 444 $menu = new action_menu(); 445 $menu->set_owner_selector('#' . $this->guess_element_id($item, $element)); 446 $menu->set_constraint('.feedback_form'); 447 $menu->set_alignment(action_menu::TR, action_menu::BR); 448 $menu->set_menu_trigger(get_string('edit')); 449 $menu->do_not_enhance(); 450 $menu->prioritise = true; 451 452 $itemobj = feedback_get_item_class($item->typ); 453 $actions = $itemobj->edit_actions($item, $this->get_feedback(), $this->get_cm()); 454 foreach ($actions as $action) { 455 $menu->add($action); 456 } 457 $editmenu = $OUTPUT->render($menu); 458 459 $name = $element->getLabel(); 460 461 $name = html_writer::span('', 'itemdd', array('id' => 'feedback_item_box_' . $item->id)) . 462 html_writer::span($name, 'itemname') . 463 html_writer::span($editmenu, 'itemactions'); 464 $element->setLabel(html_writer::span($name, 'itemtitle')); 465 } 466 467 /** 468 * Sets the default value for form element - alias to $this->_form->setDefault() 469 * @param HTML_QuickForm_element|string $element 470 * @param mixed $defaultvalue 471 */ 472 public function set_element_default($element, $defaultvalue) { 473 if ($element instanceof HTML_QuickForm_element) { 474 $element = $element->getName(); 475 } 476 $this->_form->setDefault($element, $defaultvalue); 477 } 478 479 480 /** 481 * Sets the default value for form element - wrapper to $this->_form->setType() 482 * @param HTML_QuickForm_element|string $element 483 * @param int $type 484 */ 485 public function set_element_type($element, $type) { 486 if ($element instanceof HTML_QuickForm_element) { 487 $element = $element->getName(); 488 } 489 $this->_form->setType($element, $type); 490 } 491 492 /** 493 * Adds a validation rule for the given field - wrapper for $this->_form->addRule() 494 * 495 * Do not use for 'required' rule! 496 * Required * will be added automatically, if additional validation is needed 497 * use method {@link self::add_validation_rule()} 498 * 499 * @param string $element Form element name 500 * @param string $message Message to display for invalid data 501 * @param string $type Rule type, use getRegisteredRules() to get types 502 * @param string $format (optional)Required for extra rule data 503 * @param string $validation (optional)Where to perform validation: "server", "client" 504 * @param bool $reset Client-side validation: reset the form element to its original value if there is an error? 505 * @param bool $force Force the rule to be applied, even if the target form element does not exist 506 */ 507 public function add_element_rule($element, $message, $type, $format = null, $validation = 'server', 508 $reset = false, $force = false) { 509 if ($element instanceof HTML_QuickForm_element) { 510 $element = $element->getName(); 511 } 512 $this->_form->addRule($element, $message, $type, $format, $validation, $reset, $force); 513 } 514 515 /** 516 * Adds a validation rule to the form 517 * 518 * @param callable $callback with arguments ($values, $files) 519 */ 520 public function add_validation_rule(callable $callback) { 521 if ($this->mode == self::MODE_COMPLETE) { 522 $this->_form->addFormRule($callback); 523 } 524 } 525 526 /** 527 * Returns a reference to the element - wrapper for function $this->_form->getElement() 528 * 529 * @param string $elementname Element name 530 * @return HTML_QuickForm_element reference to element 531 */ 532 public function get_form_element($elementname) { 533 return $this->_form->getElement($elementname); 534 } 535 536 /** 537 * Displays the form 538 */ 539 public function display() { 540 global $OUTPUT, $PAGE; 541 // Finalize the form definition if not yet done. 542 if (!$this->_definition_finalized) { 543 $this->_definition_finalized = true; 544 $this->definition_after_data(); 545 } 546 547 $mform = $this->_form; 548 549 // Add "This form has required fields" text in the bottom of the form. 550 if (($mform->_required || $this->hasrequired) && 551 ($this->mode == self::MODE_COMPLETE || $this->mode == self::MODE_PRINT || $this->mode == self::MODE_VIEW_TEMPLATE)) { 552 $element = $mform->addElement('static', 'requiredfields', '', 553 get_string('somefieldsrequired', 'form', 554 '<img alt="'.get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />')); 555 $element->setAttributes($element->getAttributes() + ['class' => 'requirednote']); 556 } 557 558 // Reset _required array so the default red * are not displayed. 559 $mform->_required = array(); 560 561 // Move buttons to the end of the form. 562 if ($this->mode == self::MODE_COMPLETE) { 563 $mform->addElement('hidden', '__dummyelement'); 564 $buttons = $mform->removeElement('buttonar', false); 565 $mform->insertElementBefore($buttons, '__dummyelement'); 566 $mform->removeElement('__dummyelement'); 567 } 568 569 $this->_form->display(); 570 571 if ($this->mode == self::MODE_EDIT) { 572 $PAGE->requires->js_call_amd('mod_feedback/edit', 'setup'); 573 } 574 } 575 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |