From 1fbf23311198249d487aa1cb9abc87c92023feee Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Fri, 10 May 2019 12:56:33 +1000 Subject: [PATCH] Use repeat form element for date ranges (#185) --- classes/edit_element_form.php | 1 + classes/element.php | 28 +++ element/daterange/classes/element.php | 164 +++++++----------- .../lang/en/customcertelement_daterange.php | 9 +- element/daterange/settings.php | 40 ----- element/daterange/styles.css | 3 - .../daterange/tests/phpunit/element_test.php | 9 - 7 files changed, 99 insertions(+), 155 deletions(-) delete mode 100644 element/daterange/settings.php delete mode 100644 element/daterange/styles.css diff --git a/classes/edit_element_form.php b/classes/edit_element_form.php index 350f39c..a08497d 100644 --- a/classes/edit_element_form.php +++ b/classes/edit_element_form.php @@ -64,6 +64,7 @@ class edit_element_form extends \moodleform { $mform->addHelpButton('name', 'elementname', 'customcert'); $this->element = \mod_customcert\element_factory::get_element_instance($element); + $this->element->set_edit_element_form($this); $this->element->render_form_elements($mform); $this->add_action_buttons(true); diff --git a/classes/element.php b/classes/element.php index 415f8de..4d1c8e0 100644 --- a/classes/element.php +++ b/classes/element.php @@ -102,6 +102,11 @@ abstract class element { */ protected $showposxy; + /** + * @var edit_element_form Element edit form instance. + */ + private $editelementform; + /** * Constructor. * @@ -422,4 +427,27 @@ abstract class element { return $this->element->$name; } } + + /** + * Set edit form instance for the custom cert element. + * + * @param \mod_customcert\edit_element_form $editelementform + */ + public function set_edit_element_form(edit_element_form $editelementform) { + $this->editelementform = $editelementform; + } + + /** + * Get edit form instance for the custom cert element. + * + * @return \mod_customcert\edit_element_form + */ + public function get_edit_element_form() { + if (empty($this->editelementform)) { + throw new \coding_exception('Edit element form instance is not set.'); + } + + return $this->editelementform; + } + } diff --git a/element/daterange/classes/element.php b/element/daterange/classes/element.php index 5813910..e6c56cd 100644 --- a/element/daterange/classes/element.php +++ b/element/daterange/classes/element.php @@ -74,11 +74,6 @@ class element extends \mod_customcert\element { */ const DATE_YEAR_PLACEHOLDER = '{{date_year}}'; - /** - * Default max number of dateranges per element. - */ - const DEFAULT_MAX_RANGES = 10; - /** * Date - Issue */ @@ -135,68 +130,59 @@ class element extends \mod_customcert\element { $mform->addHelpButton('fallbackstring', 'fallbackstring', 'customcertelement_daterange'); $mform->setType('fallbackstring', PARAM_NOTAGS); - if (!$maxranges = get_config('customcertelement_daterange', 'maxranges')) { - $maxranges = self::DEFAULT_MAX_RANGES; + if (empty($this->get_decoded_data()->dateranges)) { + $repeats = 1; + } else { + $repeats = count($this->get_decoded_data()->dateranges); } - if (!empty($this->get_data())) { - if ($maxranges < $this->get_decoded_data()->numranges) { - $maxranges = $this->get_decoded_data()->numranges; - } - } + $ranges = []; - $mform->addElement('hidden', 'numranges', $maxranges); - $mform->setType('numranges', PARAM_INT); + $ranges[] = $mform->createElement('html', '
'); - for ($i = 0; $i < $maxranges; $i++) { + $ranges[] = $mform->createElement( + 'date_selector', + 'startdate', + get_string('start', 'customcertelement_daterange') + ); - $mform->addElement('static', - $this->build_element_name('group', $i), - get_string('daterange', 'customcertelement_daterange', $i + 1), - '' - ); + $ranges[] = $mform->createElement( + 'date_selector', + 'enddate', + get_string('end', 'customcertelement_daterange') + ); - $mform->addElement( - 'checkbox', - $this->build_element_name('enabled', $i), - get_string('enable') - ); - $mform->setType($this->build_element_name('enabled', $i), PARAM_BOOL); + $ranges[] = $mform->createElement( + 'checkbox', + 'recurring', + get_string('recurring', 'customcertelement_daterange') + ); - $mform->addElement( - 'date_selector', - $this->build_element_name('startdate', $i), - get_string('start', 'customcertelement_daterange') - ); - $mform->setType($this->build_element_name('startdate', $i), PARAM_INT); + $ranges[] = $mform->createElement( + 'text', + 'datestring', + get_string('datestring', 'customcertelement_daterange'), + ['class' => 'datestring'] + ); - $mform->addElement( - 'date_selector', - $this->build_element_name('enddate', $i), - get_string('end', 'customcertelement_daterange') - ); - $mform->setType($this->build_element_name('enddate', $i), PARAM_INT); + $ranges[] = $mform->createElement( + 'advcheckbox', + 'rangedelete', + get_string('setdeleted', 'customcertelement_daterange'), + '', + [], + [0, 1] + ); - $mform->addElement( - 'checkbox', - $this->build_element_name('recurring', $i), - get_string('recurring', 'customcertelement_daterange') - ); - $mform->setType($this->build_element_name('recurring', $i), PARAM_BOOL); + $rangeoptions = array(); + $rangeoptions['startdate']['type'] = PARAM_INT; + $rangeoptions['enddate']['type'] = PARAM_INT; + $rangeoptions['recurring']['type'] = PARAM_INT; + $rangeoptions['datestring']['type'] = PARAM_NOTAGS; + $rangeoptions['rangedelete']['type'] = PARAM_BOOL; - $mform->addElement( - 'text', - $this->build_element_name('datestring', $i), - get_string('datestring', 'customcertelement_daterange'), - ['class' => 'datestring'] - ); - $mform->setType($this->build_element_name('datestring', $i), PARAM_NOTAGS); - - $mform->disabledIf($this->build_element_name('startdate', $i), $this->build_element_name('enabled', $i), 'notchecked'); - $mform->disabledIf($this->build_element_name('enddate', $i), $this->build_element_name('enabled', $i), 'notchecked'); - $mform->disabledIf($this->build_element_name('recurring', $i), $this->build_element_name('enabled', $i), 'notchecked'); - $mform->disabledIf($this->build_element_name('datestring', $i), $this->build_element_name('enabled', $i), 'notchecked'); - } + $addstring = get_string('addrange', 'customcertelement_daterange'); + $this->get_edit_element_form()->repeat_elements($ranges, $repeats, $rangeoptions, 'repeats', 'add', 1, $addstring, true); } /** @@ -208,7 +194,7 @@ class element extends \mod_customcert\element { * @return string */ protected function build_element_name($name, $num) { - return $name . $num; + return $name . '[' . $num . ']'; } /** @@ -233,18 +219,11 @@ class element extends \mod_customcert\element { $element = $mform->getElement('fallbackstring'); $element->setValue($this->get_decoded_data()->fallbackstring); - $element = $mform->getElement('numranges'); - $numranges = $element->getValue(); - if ($numranges < $this->get_decoded_data()->numranges) { - $element->setValue($this->get_decoded_data()->numranges); - } - foreach ($this->get_decoded_data()->dateranges as $key => $range) { $mform->setDefault($this->build_element_name('startdate', $key), $range->startdate); $mform->setDefault($this->build_element_name('enddate', $key), $range->enddate); $mform->setDefault($this->build_element_name('datestring', $key), $range->datestring); $mform->setDefault($this->build_element_name('recurring', $key), $range->recurring); - $mform->setDefault($this->build_element_name('enabled', $key), $range->enabled); } } @@ -262,9 +241,10 @@ class element extends \mod_customcert\element { $errors = parent::validate_form_elements($data, $files); // Check if at least one range is set. - $error = get_string('error:enabled', 'customcertelement_daterange'); - for ($i = 0; $i < $data['numranges']; $i++) { - if (!empty($data[$this->build_element_name('enabled', $i)])) { + $error = get_string('error:atleastone', 'customcertelement_daterange'); + + for ($i = 0; $i < $data['repeats']; $i++) { + if (empty($data['rangedelete'][$i])) { $error = ''; } } @@ -273,30 +253,27 @@ class element extends \mod_customcert\element { $errors['help'] = $error; } - // Check that datestring is set for enabled dataranges. - for ($i = 0; $i < $data['numranges']; $i++) { - $enabled = $this->build_element_name('enabled', $i); - $datestring = $this->build_element_name('datestring', $i); - if (!empty($data[$enabled]) && empty($data[$datestring])) { + // Check that datestring is set dataranges what aren't need to be deleted. + for ($i = 0; $i < $data['repeats']; $i++) { + // Skip elements that needs to be deleted. + if (!empty($data['rangedelete'][$i])) { + continue; + } + + if (empty($data['datestring'][$i])) { $name = $this->build_element_name('datestring', $i); $errors[$name] = get_string('error:datestring', 'customcertelement_daterange'); } - } - - for ($i = 0; $i < $data['numranges']; $i++) { - $enabled = $this->build_element_name('enabled', $i); - $recurring = $this->build_element_name('recurring', $i); - $startdate = $this->build_element_name('startdate', $i); - $enddate = $this->build_element_name('enddate', $i); - $rangeperiod = $data[$enddate] - $data[$startdate]; // Check that end date is correctly set. - if (!empty($data[$enabled]) && $data[$startdate] >= $data[$enddate] ) { + if ( $data['startdate'][$i] >= $data['enddate'][$i] ) { $errors[$this->build_element_name('enddate', $i)] = get_string('error:enddate', 'customcertelement_daterange'); } + $rangeperiod = $data['enddate'][$i] - $data['startdate'][$i]; + // Check that recurring dateranges are not longer than 12 months. - if (!empty($data[$recurring]) && $rangeperiod >= self::MAX_RECURRING_PERIOD ) { + if (!empty($data['recurring'][$i]) && $rangeperiod >= self::MAX_RECURRING_PERIOD ) { $errors[$this->build_element_name('enddate', $i)] = get_string('error:recurring', 'customcertelement_daterange'); } } @@ -315,26 +292,17 @@ class element extends \mod_customcert\element { $arrtostore = array( 'dateitem' => $data->dateitem, 'fallbackstring' => $data->fallbackstring, - 'numranges' => 0, 'dateranges' => [], ); - for ($i = 0; $i < $data->numranges; $i++) { - $startdate = $this->build_element_name('startdate', $i); - $enddate = $this->build_element_name('enddate', $i); - $datestring = $this->build_element_name('datestring', $i); - $recurring = $this->build_element_name('recurring', $i); - $enabled = $this->build_element_name('enabled', $i); - - if (!empty($data->$datestring)) { + for ($i = 0; $i < $data->repeats; $i++) { + if (empty($data->rangedelete[$i])) { $arrtostore['dateranges'][] = [ - 'startdate' => $data->$startdate, - 'enddate' => $data->$enddate, - 'datestring' => $data->$datestring, - 'recurring' => !empty($data->$recurring), - 'enabled' => !empty($data->$enabled), + 'startdate' => $data->startdate[$i], + 'enddate' => $data->enddate[$i], + 'datestring' => $data->datestring[$i], + 'recurring' => !empty($data->recurring[$i]), ]; - $arrtostore['numranges']++; } } diff --git a/element/daterange/lang/en/customcertelement_daterange.php b/element/daterange/lang/en/customcertelement_daterange.php index f1c2957..cecb0a0 100644 --- a/element/daterange/lang/en/customcertelement_daterange.php +++ b/element/daterange/lang/en/customcertelement_daterange.php @@ -36,17 +36,16 @@ $string['fallbackstring_help'] = 'This string will be displayed if no daterange $string['help'] = 'Configure a string representation for each daterange. Make sure your ranges do not overlap, otherwise the first matched daterange will be applied. If no daterange matched a date, then Fallback string will be displayed. If Fallback string is not set, then there will be no output.
If you mark a date range as Recurring, then the configured year will not be considered. As the year of a recurring date range is not considered, you are not allowed to configure a recurring date range with more than 12 months as it would become ambiguous otherwise.'; $string['placeholders'] = 'Also following placeholders could be used in the string representation or fallback string.
{{range_first_year}} - first year of the matched range,
{{range_last_year}} - last year of the matched range,
{{recurring_range_first_year}} - first year of the matched recurring period,
{{recurring_range_last_year}} - last year of the matched recurring period,
{{current_year}} - the current year,
{{date_year}} - a year of the users\'s date.'; $string['issueddate'] = 'Issued date'; -$string['maxranges'] = 'Maximum number ranges'; -$string['maxranges_desc'] = 'Set a maximum number of date ranges per each element'; $string['pluginname'] = 'Date range'; $string['privacy:metadata'] = 'The Date range plugin does not store any personal data.'; $string['start'] = 'Start'; $string['end'] = 'End'; $string['datestring'] = 'String'; -$string['daterange'] = 'Daterange {$a}'; -$string['error:enabled'] = 'You must have at least one datarange enabled'; -$string['error:datestring'] = 'You must provide string representation for the enabled datarange'; +$string['error:atleastone'] = 'You must have at least one date range configured'; +$string['error:datestring'] = 'You must provide string representation for the datarange'; $string['error:enddate'] = 'End date must be after Start date'; $string['error:recurring'] = 'Recurring range must not be longer than 12 months'; $string['preview'] = 'Preview {$a}'; $string['recurring'] = 'Recurring?'; +$string['setdeleted'] = 'Delete?'; +$string['addrange'] = 'Add another range'; diff --git a/element/daterange/settings.php b/element/daterange/settings.php deleted file mode 100644 index d369a03..0000000 --- a/element/daterange/settings.php +++ /dev/null @@ -1,40 +0,0 @@ -. - -/** - * Admin settings. - * - * @package customcertelement_daterange - * @copyright 2018 Dmitrii Metelkin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); - -$options = []; - -foreach (range(1, 365) as $number) { - $options[$number] = $number; -} - -$settings->add(new admin_setting_configselect( - 'customcertelement_daterange/maxranges', - get_string('maxranges', 'customcertelement_daterange'), - get_string('maxranges_desc', 'customcertelement_daterange'), - 1, - $options -)); - diff --git a/element/daterange/styles.css b/element/daterange/styles.css deleted file mode 100644 index d65b7a6..0000000 --- a/element/daterange/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.datestring { - padding-bottom: 1.5rem; -} diff --git a/element/daterange/tests/phpunit/element_test.php b/element/daterange/tests/phpunit/element_test.php index 1176de9..1936746 100644 --- a/element/daterange/tests/phpunit/element_test.php +++ b/element/daterange/tests/phpunit/element_test.php @@ -120,14 +120,12 @@ class customcertelement_daterange_element_test extends advanced_testcase { 'enddate' => strtotime('30.09.2017'), 'datestring' => 'SS {{date_year}}', 'recurring' => true, - 'enabled' => true, ], (object)[ 'startdate' => strtotime('01.10.2017'), 'enddate' => strtotime('31.03.2018'), 'datestring' => 'WS {{recurring_range_first_year}}/{{recurring_range_last_year}}', 'recurring' => true, - 'enabled' => true, ], ]; @@ -146,14 +144,12 @@ class customcertelement_daterange_element_test extends advanced_testcase { 'enddate' => strtotime('30.09.2017'), 'datestring' => 'First range', 'recurring' => false, - 'enabled' => true, ], (object)[ 'startdate' => strtotime('01.05.2017'), 'enddate' => strtotime('01.07.2018'), 'datestring' => 'Second range', 'recurring' => false, - 'enabled' => true, ], ]; @@ -172,7 +168,6 @@ class customcertelement_daterange_element_test extends advanced_testcase { 'enddate' => strtotime('30.09.2018'), 'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}', 'recurring' => false, - 'enabled' => true, ], ]; @@ -198,7 +193,6 @@ class customcertelement_daterange_element_test extends advanced_testcase { 'enddate' => strtotime('30.09.2018'), 'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}', 'recurring' => false, - 'enabled' => true, ], ]; @@ -220,16 +214,13 @@ class customcertelement_daterange_element_test extends advanced_testcase { 'enddate' => strtotime('30.09.2017'), 'datestring' => $datestring, 'recurring' => true, - 'enabled' => true, ], (object)[ 'startdate' => strtotime('01.10.2017'), 'enddate' => strtotime('31.03.2018'), 'datestring' => $datestring, 'recurring' => true, - 'enabled' => true, ], - ]; $element = $this->get_datarange_element($dateranges);