MDL-43156 formslib: newly-created repeat elements get the default values
authorDavo Smith <git@davosmith.co.uk>
Mon, 2 Dec 2013 15:22:29 +0000 (15:22 +0000)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Thu, 30 Apr 2020 18:16:07 +0000 (20:16 +0200)
lib/form/checkbox.php
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/form/duration.php
lib/form/tests/behat/fixtures/repeat_defaults_form.php [new file with mode: 0644]
lib/form/tests/behat/repeat_defaults.feature [new file with mode: 0644]
lib/formslib.php
lib/tests/behat/behat_forms.php

index 5366ebb..d76cb48 100644 (file)
@@ -101,7 +101,7 @@ class MoodleQuickForm_checkbox extends HTML_QuickForm_checkbox implements templa
                 if (null === $value) {
                     // if no boxes were checked, then there is no value in the array
                     // yet we don't want to display default value in this case
-                    if ($caller->isSubmitted()) {
+                    if ($caller->isSubmitted() && !$caller->is_new_repeat($this->getName())) {
                         $value = $this->_findValue($caller->_submitValues);
                     } else {
 
index 048b119..7d24f66 100644 (file)
@@ -168,7 +168,7 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group {
                 if (null === $value) {
                     // If no boxes were checked, then there is no value in the array
                     // yet we don't want to display default value in this case.
-                    if ($caller->isSubmitted()) {
+                    if ($caller->isSubmitted() && !$caller->is_new_repeat($this->getName())) {
                         $value = $this->_findValue($caller->_submitValues);
                     } else {
                         $value = $this->_findValue($caller->_defaultValues);
index 094b05f..9c1ff76 100644 (file)
@@ -187,7 +187,7 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group {
                 if (null === $value) {
                     // If no boxes were checked, then there is no value in the array
                     // yet we don't want to display default value in this case.
-                    if ($caller->isSubmitted()) {
+                    if ($caller->isSubmitted() && !$caller->is_new_repeat($this->getName())) {
                         $value = $this->_findValue($caller->_submitValues);
                     } else {
                         $value = $this->_findValue($caller->_defaultValues);
index ee04ff0..20c0d05 100644 (file)
@@ -218,7 +218,7 @@ class MoodleQuickForm_duration extends MoodleQuickForm_group {
                 if (null === $value) {
                     // if no boxes were checked, then there is no value in the array
                     // yet we don't want to display default value in this case
-                    if ($caller->isSubmitted()) {
+                    if ($caller->isSubmitted() && !$caller->is_new_repeat($this->getName())) {
                         $value = $this->_findValue($caller->_submitValues);
                     } else {
                         $value = $this->_findValue($caller->_defaultValues);
diff --git a/lib/form/tests/behat/fixtures/repeat_defaults_form.php b/lib/form/tests/behat/fixtures/repeat_defaults_form.php
new file mode 100644 (file)
index 0000000..1e88cc4
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Test form repeat elements + defaults
+ *
+ * @copyright 2020 Davo Smith, Synergy Learning
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(__DIR__.'/../../../../../config.php');
+
+defined('BEHAT_SITE_RUNNING') || die();
+
+global $CFG, $PAGE, $OUTPUT;
+require_once($CFG->libdir.'/formslib.php');
+$PAGE->set_url('/lib/form/tests/behat/fixtures/formtest.php');
+$PAGE->set_context(context_system::instance());
+
+class repeat_defaults_form extends moodleform {
+    public function definition() {
+        $mform = $this->_form;
+        $repeatcount = $this->_customdata['repeatcount'];
+
+        $repeat = array();
+        $repeatopts = array();
+
+        $repeat[] = $mform->createElement('header', 'testheading', 'Heading {no}');
+
+        $repeat[] = $mform->createElement('checkbox', 'testcheckbox', 'Test checkbox (default checked)');
+        $repeatopts['testcheckbox']['default'] = 1;
+
+        $repeat[] = $mform->createElement('advcheckbox', 'testadvcheckbox', 'Test advcheckbox (default checked)');
+        $repeatopts['testadvcheckbox']['default'] = 1;
+
+        $repeat[] = $mform->createElement('date_selector', 'testdate', 'Test date (default 8th Sept 2013)');
+        $repeatopts['testdate']['default'] = mktime(0, 0, 0, 9, 8, 2013);
+
+        $repeat[] = $mform->createElement('date_time_selector', 'testdatetime', 'Test datetime (default 8th Sept 2013, 10:30am)');
+        $repeatopts['testdatetime']['default'] = mktime(10, 30, 0, 9, 8, 2013);
+
+        $repeat[] = $mform->createElement('duration', 'testduration', 'Test duration (default 3 hours)');
+        $repeatopts['testduration']['default'] = 3 * HOURSECS;
+
+        $repeat[] = $mform->createElement('select', 'testselect', 'Test select (default B)', array(1 => 'A', 2 => 'B', 3 => 'C'));
+        $repeatopts['testselect']['default'] = 2;
+
+        $repeat[] = $mform->createElement('selectyesno', 'testselectyes', 'Test selectyesno (default yes)');
+        $repeatopts['testselectyes']['default'] = 1;
+
+        $repeat[] = $mform->createElement('selectyesno', 'testselectno', 'Test selectyesno (default no)');
+        $repeatopts['testselectno']['default'] = 0;
+
+        $repeat[] = $mform->createElement('text', 'testtext', 'Test text (default \'Testing 123\')');
+        $repeatopts['testtext']['default'] = 'Testing 123';
+        $repeatopts['testtext']['type'] = PARAM_TEXT;
+
+        $this->repeat_elements($repeat, $repeatcount, $repeatopts, 'test_repeat', 'test_repeat_add', 1, 'Add repeats', true);
+
+        $this->add_action_buttons();
+    }
+}
+
+$repeatcount = optional_param('test_repeat', 1, PARAM_INT);
+$form = new repeat_defaults_form(null, array('repeatcount' => $repeatcount));
+
+echo $OUTPUT->header();
+$form->display();
+echo $OUTPUT->footer();
diff --git a/lib/form/tests/behat/repeat_defaults.feature b/lib/form/tests/behat/repeat_defaults.feature
new file mode 100644 (file)
index 0000000..bb88179
--- /dev/null
@@ -0,0 +1,23 @@
+@core_form @javascript
+Feature: Newly created repeat elements have the correct default values
+
+  Scenario: Clicking button to add repeat elements creates repeat elements with the correct default values
+    Given I am on the repeat defaults form page
+    When I press "Add repeats"
+    Then the following fields match these values:
+      | testcheckbox[1]           | 1           |
+      | testadvcheckbox[1]        | 1           |
+      | testdate[1][day]          | 8           |
+      | testdate[1][month]        | September   |
+      | testdate[1][year]         | 2013        |
+      | testdatetime[1][day]      | 8           |
+      | testdatetime[1][month]    | September   |
+      | testdatetime[1][year]     | 2013        |
+      | testdatetime[1][hour]     | 10          |
+      | testdatetime[1][minute]   | 30          |
+      | testduration[1][number]   | 3           |
+      | testduration[1][timeunit] | hours       |
+      | testselect[1]             | B           |
+      | testselectyes[1]          | Yes         |
+      | testselectno[1]           | No          |
+      | testtext[1]               | Testing 123 |
index 4a000a3..74a7226 100644 (file)
@@ -1110,6 +1110,7 @@ abstract class moodleform {
         }
         $repeats = $this->optional_param($repeathiddenname, $repeats, PARAM_INT);
         $addfields = $this->optional_param($addfieldsname, '', PARAM_TEXT);
+        $oldrepeats = $repeats;
         if (!empty($addfields)){
             $repeats += $addfieldsno;
         }
@@ -1132,6 +1133,11 @@ abstract class moodleform {
                     $elementclone->setLabel(str_replace('{no}', $i + 1, $elementclone->getLabel()));
                 }
 
+                // Mark newly created elements, so they know not to look for any submitted data.
+                if ($i >= $oldrepeats) {
+                    $mform->note_new_repeat($elementclone->getName());
+                }
+
                 $mform->addElement($elementclone);
             }
         }
@@ -1542,6 +1548,9 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
      */
     var $_pageparams = '';
 
+    /** @var array names of new repeating elements that should not expect to find submitted data */
+    protected $_newrepeats = array();
+
     /** @var array $_ajaxformdata submitted form data when using mforms with ajax */
     protected $_ajaxformdata;
 
@@ -2867,6 +2876,28 @@ require(["core/event", "jquery"], function(Event, $) {
     {
         return parent::isSubmitted() && (!$this->isFrozen());
     }
+
+    /**
+     * Add the element name to the list of newly-created repeat elements
+     * (So that elements that interpret 'no data submitted' as a valid state
+     * can tell when they should get the default value instead).
+     *
+     * @param string $name the name of the new element
+     */
+    public function note_new_repeat($name) {
+        $this->_newrepeats[] = $name;
+    }
+
+    /**
+     * Check if the element with the given name has just been added by clicking
+     * on the 'Add repeating elements' button.
+     *
+     * @param string $name the name of the element being checked
+     * @return bool true if the element is newly added
+     */
+    public function is_new_repeat($name) {
+        return in_array($name, $this->_newrepeats);
+    }
 }
 
 /**
index d81686e..944c7e1 100644 (file)
@@ -731,4 +731,13 @@ class behat_forms extends behat_base {
         $node = $this->get_node_in_container('xpath_element', $xpathtarget, 'form_row', $field);
         $this->ensure_node_is_visible($node);
     }
+
+    /**
+     * Visit the fixture page for testing repeat defaults.
+     * @Given /^I am on the repeat defaults form page$/
+     */
+    public function i_am_on_the_repeat_defaults_form_page() {
+        $url = new moodle_url('/lib/form/tests/behat/fixtures/repeat_defaults_form.php');
+        $this->getSession()->visit($this->locate_path($url->out_as_local_url(false)));
+    }
 }