Use repeat form element for date ranges (#185)

This commit is contained in:
Dmitrii Metelkin 2019-05-10 12:56:33 +10:00 committed by Mark Nelson
parent 2866aa7c6b
commit 4d62cde7f3
7 changed files with 99 additions and 155 deletions

View file

@ -64,6 +64,7 @@ class edit_element_form extends \moodleform {
$mform->addHelpButton('name', 'elementname', 'customcert'); $mform->addHelpButton('name', 'elementname', 'customcert');
$this->element = \mod_customcert\element_factory::get_element_instance($element); $this->element = \mod_customcert\element_factory::get_element_instance($element);
$this->element->set_edit_element_form($this);
$this->element->render_form_elements($mform); $this->element->render_form_elements($mform);
$this->add_action_buttons(true); $this->add_action_buttons(true);

View file

@ -102,6 +102,11 @@ abstract class element {
*/ */
protected $showposxy; protected $showposxy;
/**
* @var edit_element_form Element edit form instance.
*/
private $editelementform;
/** /**
* Constructor. * Constructor.
* *
@ -421,4 +426,27 @@ abstract class element {
return $this->element->$name; 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;
}
} }

View file

@ -74,11 +74,6 @@ class element extends \mod_customcert\element {
*/ */
const DATE_YEAR_PLACEHOLDER = '{{date_year}}'; const DATE_YEAR_PLACEHOLDER = '{{date_year}}';
/**
* Default max number of dateranges per element.
*/
const DEFAULT_MAX_RANGES = 10;
/** /**
* Date - Issue * Date - Issue
*/ */
@ -135,68 +130,59 @@ class element extends \mod_customcert\element {
$mform->addHelpButton('fallbackstring', 'fallbackstring', 'customcertelement_daterange'); $mform->addHelpButton('fallbackstring', 'fallbackstring', 'customcertelement_daterange');
$mform->setType('fallbackstring', PARAM_NOTAGS); $mform->setType('fallbackstring', PARAM_NOTAGS);
if (!$maxranges = get_config('customcertelement_daterange', 'maxranges')) { if (empty($this->get_decoded_data()->dateranges)) {
$maxranges = self::DEFAULT_MAX_RANGES; $repeats = 1;
} else {
$repeats = count($this->get_decoded_data()->dateranges);
} }
if (!empty($this->get_data())) { $ranges = [];
if ($maxranges < $this->get_decoded_data()->numranges) {
$maxranges = $this->get_decoded_data()->numranges;
}
}
$mform->addElement('hidden', 'numranges', $maxranges); $ranges[] = $mform->createElement('html', '<hr>');
$mform->setType('numranges', PARAM_INT);
for ($i = 0; $i < $maxranges; $i++) { $ranges[] = $mform->createElement(
'date_selector',
'startdate',
get_string('start', 'customcertelement_daterange')
);
$mform->addElement('static', $ranges[] = $mform->createElement(
$this->build_element_name('group', $i), 'date_selector',
get_string('daterange', 'customcertelement_daterange', $i + 1), 'enddate',
'' get_string('end', 'customcertelement_daterange')
); );
$mform->addElement( $ranges[] = $mform->createElement(
'checkbox', 'checkbox',
$this->build_element_name('enabled', $i), 'recurring',
get_string('enable') get_string('recurring', 'customcertelement_daterange')
); );
$mform->setType($this->build_element_name('enabled', $i), PARAM_BOOL);
$mform->addElement( $ranges[] = $mform->createElement(
'date_selector', 'text',
$this->build_element_name('startdate', $i), 'datestring',
get_string('start', 'customcertelement_daterange') get_string('datestring', 'customcertelement_daterange'),
); ['class' => 'datestring']
$mform->setType($this->build_element_name('startdate', $i), PARAM_INT); );
$mform->addElement( $ranges[] = $mform->createElement(
'date_selector', 'advcheckbox',
$this->build_element_name('enddate', $i), 'rangedelete',
get_string('end', 'customcertelement_daterange') get_string('setdeleted', 'customcertelement_daterange'),
); '',
$mform->setType($this->build_element_name('enddate', $i), PARAM_INT); [],
[0, 1]
);
$mform->addElement( $rangeoptions = array();
'checkbox', $rangeoptions['startdate']['type'] = PARAM_INT;
$this->build_element_name('recurring', $i), $rangeoptions['enddate']['type'] = PARAM_INT;
get_string('recurring', 'customcertelement_daterange') $rangeoptions['recurring']['type'] = PARAM_INT;
); $rangeoptions['datestring']['type'] = PARAM_NOTAGS;
$mform->setType($this->build_element_name('recurring', $i), PARAM_BOOL); $rangeoptions['rangedelete']['type'] = PARAM_BOOL;
$mform->addElement( $addstring = get_string('addrange', 'customcertelement_daterange');
'text', $this->get_edit_element_form()->repeat_elements($ranges, $repeats, $rangeoptions, 'repeats', 'add', 1, $addstring, true);
$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');
}
} }
/** /**
@ -208,7 +194,7 @@ class element extends \mod_customcert\element {
* @return string * @return string
*/ */
protected function build_element_name($name, $num) { 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 = $mform->getElement('fallbackstring');
$element->setValue($this->get_decoded_data()->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) { 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('startdate', $key), $range->startdate);
$mform->setDefault($this->build_element_name('enddate', $key), $range->enddate); $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('datestring', $key), $range->datestring);
$mform->setDefault($this->build_element_name('recurring', $key), $range->recurring); $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); $errors = parent::validate_form_elements($data, $files);
// Check if at least one range is set. // Check if at least one range is set.
$error = get_string('error:enabled', 'customcertelement_daterange'); $error = get_string('error:atleastone', 'customcertelement_daterange');
for ($i = 0; $i < $data['numranges']; $i++) {
if (!empty($data[$this->build_element_name('enabled', $i)])) { for ($i = 0; $i < $data['repeats']; $i++) {
if (empty($data['rangedelete'][$i])) {
$error = ''; $error = '';
} }
} }
@ -273,30 +253,27 @@ class element extends \mod_customcert\element {
$errors['help'] = $error; $errors['help'] = $error;
} }
// Check that datestring is set for enabled dataranges. // Check that datestring is set dataranges what aren't need to be deleted.
for ($i = 0; $i < $data['numranges']; $i++) { for ($i = 0; $i < $data['repeats']; $i++) {
$enabled = $this->build_element_name('enabled', $i); // Skip elements that needs to be deleted.
$datestring = $this->build_element_name('datestring', $i); if (!empty($data['rangedelete'][$i])) {
if (!empty($data[$enabled]) && empty($data[$datestring])) { continue;
}
if (empty($data['datestring'][$i])) {
$name = $this->build_element_name('datestring', $i); $name = $this->build_element_name('datestring', $i);
$errors[$name] = get_string('error:datestring', 'customcertelement_daterange'); $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. // 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'); $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. // 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'); $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( $arrtostore = array(
'dateitem' => $data->dateitem, 'dateitem' => $data->dateitem,
'fallbackstring' => $data->fallbackstring, 'fallbackstring' => $data->fallbackstring,
'numranges' => 0,
'dateranges' => [], 'dateranges' => [],
); );
for ($i = 0; $i < $data->numranges; $i++) { for ($i = 0; $i < $data->repeats; $i++) {
$startdate = $this->build_element_name('startdate', $i); if (empty($data->rangedelete[$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)) {
$arrtostore['dateranges'][] = [ $arrtostore['dateranges'][] = [
'startdate' => $data->$startdate, 'startdate' => $data->startdate[$i],
'enddate' => $data->$enddate, 'enddate' => $data->enddate[$i],
'datestring' => $data->$datestring, 'datestring' => $data->datestring[$i],
'recurring' => !empty($data->$recurring), 'recurring' => !empty($data->recurring[$i]),
'enabled' => !empty($data->$enabled),
]; ];
$arrtostore['numranges']++;
} }
} }

View file

@ -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.<br/> 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['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.<br/> 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. <br/> {{range_first_year}} - first year of the matched range,<br/> {{range_last_year}} - last year of the matched range,<br/> {{recurring_range_first_year}} - first year of the matched recurring period,<br/> {{recurring_range_last_year}} - last year of the matched recurring period,<br/> {{current_year}} - the current year,<br/> {{date_year}} - a year of the users\'s date.'; $string['placeholders'] = 'Also following placeholders could be used in the string representation or fallback string. <br/> {{range_first_year}} - first year of the matched range,<br/> {{range_last_year}} - last year of the matched range,<br/> {{recurring_range_first_year}} - first year of the matched recurring period,<br/> {{recurring_range_last_year}} - last year of the matched recurring period,<br/> {{current_year}} - the current year,<br/> {{date_year}} - a year of the users\'s date.';
$string['issueddate'] = 'Issued 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['pluginname'] = 'Date range';
$string['privacy:metadata'] = 'The Date range plugin does not store any personal data.'; $string['privacy:metadata'] = 'The Date range plugin does not store any personal data.';
$string['start'] = 'Start'; $string['start'] = 'Start';
$string['end'] = 'End'; $string['end'] = 'End';
$string['datestring'] = 'String'; $string['datestring'] = 'String';
$string['daterange'] = 'Daterange {$a}'; $string['error:atleastone'] = 'You must have at least one date range configured';
$string['error:enabled'] = 'You must have at least one datarange enabled'; $string['error:datestring'] = 'You must provide string representation for the datarange';
$string['error:datestring'] = 'You must provide string representation for the enabled datarange';
$string['error:enddate'] = 'End date must be after Start date'; $string['error:enddate'] = 'End date must be after Start date';
$string['error:recurring'] = 'Recurring range must not be longer than 12 months'; $string['error:recurring'] = 'Recurring range must not be longer than 12 months';
$string['preview'] = 'Preview {$a}'; $string['preview'] = 'Preview {$a}';
$string['recurring'] = 'Recurring?'; $string['recurring'] = 'Recurring?';
$string['setdeleted'] = 'Delete?';
$string['addrange'] = 'Add another range';

View file

@ -1,40 +0,0 @@
<?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/>.
/**
* Admin settings.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @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
));

View file

@ -1,3 +0,0 @@
.datestring {
padding-bottom: 1.5rem;
}

View file

@ -120,14 +120,12 @@ class customcertelement_daterange_element_test extends advanced_testcase {
'enddate' => strtotime('30.09.2017'), 'enddate' => strtotime('30.09.2017'),
'datestring' => 'SS {{date_year}}', 'datestring' => 'SS {{date_year}}',
'recurring' => true, 'recurring' => true,
'enabled' => true,
], ],
(object)[ (object)[
'startdate' => strtotime('01.10.2017'), 'startdate' => strtotime('01.10.2017'),
'enddate' => strtotime('31.03.2018'), 'enddate' => strtotime('31.03.2018'),
'datestring' => 'WS {{recurring_range_first_year}}/{{recurring_range_last_year}}', 'datestring' => 'WS {{recurring_range_first_year}}/{{recurring_range_last_year}}',
'recurring' => true, 'recurring' => true,
'enabled' => true,
], ],
]; ];
@ -146,14 +144,12 @@ class customcertelement_daterange_element_test extends advanced_testcase {
'enddate' => strtotime('30.09.2017'), 'enddate' => strtotime('30.09.2017'),
'datestring' => 'First range', 'datestring' => 'First range',
'recurring' => false, 'recurring' => false,
'enabled' => true,
], ],
(object)[ (object)[
'startdate' => strtotime('01.05.2017'), 'startdate' => strtotime('01.05.2017'),
'enddate' => strtotime('01.07.2018'), 'enddate' => strtotime('01.07.2018'),
'datestring' => 'Second range', 'datestring' => 'Second range',
'recurring' => false, 'recurring' => false,
'enabled' => true,
], ],
]; ];
@ -172,7 +168,6 @@ class customcertelement_daterange_element_test extends advanced_testcase {
'enddate' => strtotime('30.09.2018'), 'enddate' => strtotime('30.09.2018'),
'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}', 'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}',
'recurring' => false, 'recurring' => false,
'enabled' => true,
], ],
]; ];
@ -198,7 +193,6 @@ class customcertelement_daterange_element_test extends advanced_testcase {
'enddate' => strtotime('30.09.2018'), 'enddate' => strtotime('30.09.2018'),
'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}', 'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}',
'recurring' => false, 'recurring' => false,
'enabled' => true,
], ],
]; ];
@ -220,16 +214,13 @@ class customcertelement_daterange_element_test extends advanced_testcase {
'enddate' => strtotime('30.09.2017'), 'enddate' => strtotime('30.09.2017'),
'datestring' => $datestring, 'datestring' => $datestring,
'recurring' => true, 'recurring' => true,
'enabled' => true,
], ],
(object)[ (object)[
'startdate' => strtotime('01.10.2017'), 'startdate' => strtotime('01.10.2017'),
'enddate' => strtotime('31.03.2018'), 'enddate' => strtotime('31.03.2018'),
'datestring' => $datestring, 'datestring' => $datestring,
'recurring' => true, 'recurring' => true,
'enabled' => true,
], ],
]; ];
$element = $this->get_datarange_element($dateranges); $element = $this->get_datarange_element($dateranges);