Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

MDL-27242 Conditional availability dates should support time as well …

…as day

Change also adds minor feature to date-time selector so you can specify the time it uses as default when the value is 0 (disabled).

Credit: This feature was developed collaboratively by Charles Fulton, Neill Magill, and me.
  • Loading branch information...
commit 6282381d05a62b032c20d25b7b29d8ead41cfbbd 1 parent 6731a04
@sammarshallou sammarshallou authored
View
12 course/modedit.php
@@ -302,12 +302,6 @@
if (!empty($CFG->enableavailability)) {
$cm->availablefrom = $fromform->availablefrom;
$cm->availableuntil = $fromform->availableuntil;
- // The form time is midnight, but because we want it to be
- // inclusive, set it to 23:59:59 on that day.
- if ($cm->availableuntil) {
- $cm->availableuntil = strtotime('23:59:59',
- $cm->availableuntil);
- }
$cm->showavailability = $fromform->showavailability;
condition_info::update_cm_from_form($cm,$fromform,true);
}
@@ -393,12 +387,6 @@
if(!empty($CFG->enableavailability)) {
$newcm->availablefrom = $fromform->availablefrom;
$newcm->availableuntil = $fromform->availableuntil;
- // The form time is midnight, but because we want it to be
- // inclusive, set it to 23:59:59 on that day.
- if ($newcm->availableuntil) {
- $newcm->availableuntil = strtotime('23:59:59',
- $newcm->availableuntil);
- }
$newcm->showavailability = $fromform->showavailability;
}
if (isset($fromform->showdescription)) {
View
21 course/moodleform_mod.php
@@ -308,7 +308,7 @@ function validation($data, $files) {
// Conditions: Don't let them set dates which make no sense
if (array_key_exists('availablefrom', $data) &&
$data['availablefrom'] && $data['availableuntil'] &&
- $data['availablefrom'] > $data['availableuntil']) {
+ $data['availablefrom'] >= $data['availableuntil']) {
$errors['availablefrom'] = get_string('badavailabledates', 'condition');
}
@@ -429,10 +429,23 @@ function standard_coursemodule_elements(){
if (!empty($CFG->enableavailability)) {
// Conditional availability
- $mform->addElement('header', 'availabilityconditionsheader', get_string('availabilityconditions', 'condition'));
- $mform->addElement('date_selector', 'availablefrom', get_string('availablefrom', 'condition'), array('optional'=>true));
+
+ // Available from/to defaults to midnight because then the display
+ // will be nicer where it tells users when they can access it (it
+ // shows only the date and not time).
+ $date = usergetdate(time());
+ $midnight = make_timestamp($date['year'], $date['mon'], $date['mday']);
+
+ // From/until controls
+ $mform->addElement('header', 'availabilityconditionsheader',
+ get_string('availabilityconditions', 'condition'));
+ $mform->addElement('date_time_selector', 'availablefrom',
+ get_string('availablefrom', 'condition'),
+ array('optional' => true, 'defaulttime' => $midnight));
$mform->addHelpButton('availablefrom', 'availablefrom', 'condition');
- $mform->addElement('date_selector', 'availableuntil', get_string('availableuntil', 'condition'), array('optional'=>true));
+ $mform->addElement('date_time_selector', 'availableuntil',
+ get_string('availableuntil', 'condition'),
+ array('optional' => true, 'defaulttime' => $midnight));
// Conditions based on grades
$gradeoptions = array();
View
1  lang/en/condition.php
@@ -57,6 +57,7 @@
$string['requires_date'] = 'Available from {$a}.';
$string['requires_date_before'] = 'Available until {$a}.';
$string['requires_date_both'] = 'Available from {$a->from} to {$a->until}.';
+$string['requires_date_both_single_day'] = 'Available on {$a}.';
$string['requires_grade_any'] = 'Not available until you have a grade in <strong>{$a}</strong>.';
$string['requires_grade_max'] = 'Not available unless you get an appropriate score in <strong>{$a}</strong>.';
$string['requires_grade_min'] = 'Not available until you achieve a required score in <strong>{$a}</strong>.';
View
103 lib/conditionlib.php
@@ -331,18 +331,66 @@ public function get_full_information($modinfo=null) {
}
}
- // Dates
+ // The date logic is complicated. The intention of this logic is:
+ // 1) display date without time where possible (whenever the date is
+ // midnight)
+ // 2) when the 'until' date is e.g. 00:00 on the 14th, we display it as
+ // 'until the 13th' (experience at the OU showed that students are
+ // likely to interpret 'until <date>' as 'until the end of <date>').
+ // 3) This behaviour becomes confusing for 'same-day' dates where there
+ // are some exceptions.
+ // Users in different time zones will typically not get the 'abbreviated'
+ // behaviour but it should work OK for them aside from that.
+
+ // The following cases are possible:
+ // a) From 13:05 on 14 Oct until 12:10 on 17 Oct (exact, exact)
+ // b) From 14 Oct until 12:11 on 17 Oct (midnight, exact)
+ // c) From 13:05 on 14 Oct until 17 Oct (exact, midnight 18 Oct)
+ // d) From 14 Oct until 17 Oct (midnight 14 Oct, midnight 18 Oct)
+ // e) On 14 Oct (midnight 14 Oct, midnight 15 Oct)
+ // f) From 13:05 on 14 Oct until 0:00 on 15 Oct (exact, midnight, same day)
+ // g) From 0:00 on 14 Oct until 12:05 on 14 Oct (midnight, exact, same day)
+ // h) From 13:05 on 14 Oct (exact)
+ // i) From 14 Oct (midnight)
+ // j) Until 13:05 on 14 Oct (exact)
+ // k) Until 14 Oct (midnight 15 Oct)
+
+ // Check if start and end dates are 'midnights', if so we show in short form
+ $shortfrom = self::is_midnight($this->cm->availablefrom);
+ $shortuntil = self::is_midnight($this->cm->availableuntil);
+
+ // For some checks and for display, we need the previous day for the 'until'
+ // value, if we are going to display it in short form
+ if ($this->cm->availableuntil) {
+ $daybeforeuntil = strtotime("-1 day", usergetmidnight($this->cm->availableuntil));
+ }
+
+ // Special case for if one but not both are exact and they are within a day
+ if ($this->cm->availablefrom && $this->cm->availableuntil &&
+ $shortfrom != $shortuntil && $daybeforeuntil < $this->cm->availablefrom) {
+ // Don't use abbreviated version (see examples f, g above)
+ $shortfrom = false;
+ $shortuntil = false;
+ }
+
+ // When showing short end date, the display time is the 'day before' one
+ $displayuntil = $shortuntil ? $daybeforeuntil : $this->cm->availableuntil;
+
if ($this->cm->availablefrom && $this->cm->availableuntil) {
- $information .= get_string('requires_date_both', 'condition',
- (object)array(
- 'from' => self::show_time($this->cm->availablefrom, false),
- 'until' => self::show_time($this->cm->availableuntil, true)));
+ if ($shortfrom && $shortuntil && $daybeforeuntil == $this->cm->availablefrom) {
+ $information .= get_string('requires_date_both_single_day', 'condition',
+ self::show_time($this->cm->availablefrom, true));
+ } else {
+ $information .= get_string('requires_date_both', 'condition', (object)array(
+ 'from' => self::show_time($this->cm->availablefrom, $shortfrom),
+ 'until' => self::show_time($displayuntil, $shortuntil)));
+ }
} else if ($this->cm->availablefrom) {
$information .= get_string('requires_date', 'condition',
- self::show_time($this->cm->availablefrom, false));
+ self::show_time($this->cm->availablefrom, $shortfrom));
} else if ($this->cm->availableuntil) {
$information .= get_string('requires_date_before', 'condition',
- self::show_time($this->cm->availableuntil, true));
+ self::show_time($displayuntil, $shortuntil));
}
$information = trim($information);
@@ -350,6 +398,17 @@ public function get_full_information($modinfo=null) {
}
/**
+ * Checks whether a given time refers exactly to midnight (in current user
+ * timezone).
+ * @param int $time Time
+ * @return bool True if time refers to midnight, false if it's some other
+ * time or if it is set to zero
+ */
+ private static function is_midnight($time) {
+ return $time && usergetmidnight($time) == $time;
+ }
+
+ /**
* Determines whether this particular course-module is currently available
* according to these criteria.
*
@@ -467,7 +526,8 @@ public function is_available(&$information, $grabthelot=false, $userid=0, $modin
$available = false;
$information .= get_string('requires_date', 'condition',
- self::show_time($this->cm->availablefrom, false));
+ self::show_time($this->cm->availablefrom,
+ self::is_midnight($this->cm->availablefrom)));
}
}
@@ -491,30 +551,15 @@ public function is_available(&$information, $grabthelot=false, $userid=0, $modin
}
/**
- * Shows a time either as a date (if it falls exactly on the day) or
- * a full date and time, according to user's timezone.
- *
+ * Shows a time either as a date or a full date and time, according to
+ * user's timezone.
* @param int $time Time
- * @param bool $until True if this date should be treated as the second of
- * an inclusive pair - if so the time will be shown unless date is 23:59:59.
- * Without this the date shows for 0:00:00.
+ * @param bool $dateonly If true, uses date only
* @return string Date
*/
- private function show_time($time, $until) {
- // Break down the time into fields
- $userdate = usergetdate($time);
-
- // Handle the 'inclusive' second date
- if($until) {
- $dateonly = $userdate['hours']==23 && $userdate['minutes']==59 &&
- $userdate['seconds']==59;
- } else {
- $dateonly = $userdate['hours']==0 && $userdate['minutes']==0 &&
- $userdate['seconds']==0;
- }
-
- return userdate($time, get_string(
- $dateonly ? 'strftimedate' : 'strftimedatetime', 'langconfig'));
+ private function show_time($time, $dateonly) {
+ return userdate($time,
+ get_string($dateonly ? 'strftimedate' : 'strftimedatetime', 'langconfig'));
}
/**
View
18 lib/db/upgrade.php
@@ -6792,6 +6792,24 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2011100700.02);
}
+ if ($oldversion < 2011101200.01) {
+ // The conditional availability date system used to rely on dates being
+ // set to 23:59:59 for the end date, but now that exact times are
+ // supported, it uses midnight on the following day.
+
+ // The query is restricted on 'time mod 10 = 9' in order that
+ // it is safe to run this upgrade twice if something goes wrong.
+ $DB->execute('UPDATE {course_modules} SET availableuntil = availableuntil + 1 ' .
+ 'WHERE availableuntil > 0 AND ' . $DB->sql_modulo('availableuntil', 10) . ' = 9');
+
+ // Because availableuntil is stored in modinfo, we need to clear modinfo
+ // for all courses.
+ rebuild_course_cache(0, true);
+
+ // Main savepoint reached
+ upgrade_main_savepoint(true, 2011101200.01);
+ }
+
return true;
}
View
8 lib/form/datetimeselector.php
@@ -40,12 +40,13 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
*
* startyear => integer start of range of years that can be selected
* stopyear => integer last year that can be selected
+ * defaulttime => default time value if the field is currently not set
* timezone => float/string timezone
* applydst => apply users daylight savings adjustment?
* step => step to increment minutes by
* optional => if true, show a checkbox beside the date to turn it on (or off)
*/
- var $_options = array('startyear' => 1970, 'stopyear' => 2020,
+ var $_options = array('startyear' => 1970, 'stopyear' => 2020, 'defaulttime' => 0,
'timezone' => 99, 'applydst' => true, 'step' => 5, 'optional' => false);
/**
@@ -159,7 +160,10 @@ function onQuickFormEvent($event, $arg, &$caller)
}
$requestvalue=$value;
if ($value == 0) {
- $value = time();
+ $value = $this->_options['defaulttime'];
+ if (!$value) {
+ $value = time();
+ }
}
if (!is_array($value)) {
$currentdate = usergetdate($value);
View
2  version.php
@@ -31,7 +31,7 @@
-$version = 2011101200.00; // YYYYMMDD = weekly release date of this DEV branch
+$version = 2011101200.01; // YYYYMMDD = weekly release date of this DEV branch
// RR = release increments - 00 in DEV branches
// .XX = incremental changes

0 comments on commit 6282381

Please sign in to comment.
Something went wrong with that request. Please try again.