From 6dd59aabfae39566ec32a3108ebf848f87243b88 Mon Sep 17 00:00:00 2001 From: Shamim Rezaie Date: Mon, 10 Jun 2013 12:47:43 +0800 Subject: [PATCH 01/16] MDL-18375 calendar: added multiple calendar support Conflicts: course/edit_form.php lib/db/install.xml lib/form/dateselector.php lib/form/datetimeselector.php lib/setup.php --- admin/settings/appearance.php | 2 + admin/settings/plugins.php | 7 + admin/tool/uploaduser/index.php | 4 +- .../calendar_month/block_calendar_month.php | 41 ++- calendar/event.php | 5 +- calendar/export_execute.php | 28 +- calendar/lib.php | 31 +- calendar/renderer.php | 10 +- calendar/view.php | 3 +- calendarsystem/admin.php | 98 +++++ calendarsystem/calendarsystem.class.php | 69 ++++ calendarsystem/gregorian/calendarsystem.php | 88 +++++ .../lang/en/calendarsystem_gregorian.php | 8 + .../lang/fa/calendarsystem_gregorian.php | 8 + calendarsystem/gregorian/version.php | 31 ++ calendarsystem/hijri/calendarsystem.php | 250 +++++++++++++ .../hijri/lang/en/calendarsystem_hijri.php | 27 ++ .../hijri/lang/fa/calendarsystem_hijri.php | 27 ++ calendarsystem/hijri/version.php | 31 ++ calendarsystem/index.php | 175 +++++++++ calendarsystem/jalali/calendarsystem.php | 289 +++++++++++++++ .../jalali/lang/en/calendarsystem_jalali.php | 27 ++ .../jalali/lang/fa/calendarsystem_jalali.php | 27 ++ calendarsystem/jalali/version.php | 31 ++ calendarsystem/updatechecker.php | 341 ++++++++++++++++++ calendarsystem/version.php | 28 ++ course/edit_form.php | 7 + enrol/manual/ajax.php | 4 +- enrol/manual/lib.php | 4 +- enrol/manual/manage.php | 5 +- lang/en/calendarsystem.php | 19 + lang/en/plugin.php | 1 + lib/bennu/iCalendar_rfc2445.php | 4 +- lib/db/install.xml | 2 + lib/form/dateselector.php | 22 +- lib/form/datetimeselector.php | 22 +- lib/moodlelib.php | 52 ++- lib/setup.php | 28 ++ user/editlib.php | 4 + user/profile/field/datetime/define.class.php | 6 +- 40 files changed, 1806 insertions(+), 60 deletions(-) create mode 100644 calendarsystem/admin.php create mode 100644 calendarsystem/calendarsystem.class.php create mode 100644 calendarsystem/gregorian/calendarsystem.php create mode 100644 calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php create mode 100644 calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php create mode 100644 calendarsystem/gregorian/version.php create mode 100644 calendarsystem/hijri/calendarsystem.php create mode 100644 calendarsystem/hijri/lang/en/calendarsystem_hijri.php create mode 100644 calendarsystem/hijri/lang/fa/calendarsystem_hijri.php create mode 100644 calendarsystem/hijri/version.php create mode 100644 calendarsystem/index.php create mode 100644 calendarsystem/jalali/calendarsystem.php create mode 100644 calendarsystem/jalali/lang/en/calendarsystem_jalali.php create mode 100644 calendarsystem/jalali/lang/fa/calendarsystem_jalali.php create mode 100644 calendarsystem/jalali/version.php create mode 100644 calendarsystem/updatechecker.php create mode 100644 calendarsystem/version.php create mode 100644 lang/en/calendarsystem.php diff --git a/admin/settings/appearance.php b/admin/settings/appearance.php index 1ee3a7ad2c41a..b5293df9ab551 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -45,6 +45,8 @@ array('0' => new lang_string('default', 'calendar'), '%I:%M %p' => new lang_string('timeformat_12', 'calendar'), '%H:%M' => new lang_string('timeformat_24', 'calendar')))); + // MDL-18375, Multi-Calendar Support + $temp->add(new admin_setting_configselect('calendarsystem', new lang_string('configcalendarsystem', 'calendarsystem'), new lang_string('helpcalendarsystem', 'calendarsystem'), 'gregorian', get_list_of_calendars())); $temp->add(new admin_setting_configselect('calendar_startwday', new lang_string('configstartwday', 'admin'), new lang_string('helpstartofweek', 'admin'), 0, array( 0 => new lang_string('sunday', 'calendar'), diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index 502d5e667ad37..4587d3412ee67 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -454,6 +454,13 @@ } } +// calendarsystem plugins +if ($hassiteconfig) { + $ADMIN->add('modules', new admin_category('calendarsystems', new lang_string('calendarsystems', 'calendarsystem'))); + $ADMIN->add('calendarsystems', new admin_externalpage('managecalendarsystems', new lang_string('calendarsystemsmanage', 'calendarsystem'), $CFG->wwwroot .'/calendarsystem/admin.php')); + $ADMIN->add('calendarsystems', new admin_externalpage('updatecalendarsystems', new lang_string('checkforupdates', 'calendarsystem'), $CFG->wwwroot .'/calendarsystem/index.php')); +} + /// Add all local plugins - must be always last! if ($hassiteconfig) { $ADMIN->add('modules', new admin_category('localplugins', new lang_string('localplugins'))); diff --git a/admin/tool/uploaduser/index.php b/admin/tool/uploaduser/index.php index 7949d94eada6b..d2144139cca09 100644 --- a/admin/tool/uploaduser/index.php +++ b/admin/tool/uploaduser/index.php @@ -81,8 +81,10 @@ $returnurl = new moodle_url('/admin/tool/uploaduser/index.php'); $bulknurl = new moodle_url('/admin/user/user_bulk.php'); +// MDL-18375, Multi-Calendar Support +$calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); -$today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); +$today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); // array of all valid fields for validation $STD_FIELDS = array('id', 'firstname', 'lastname', 'username', 'email', diff --git a/blocks/calendar_month/block_calendar_month.php b/blocks/calendar_month/block_calendar_month.php index abe28089e9e47..11e816264a951 100644 --- a/blocks/calendar_month/block_calendar_month.php +++ b/blocks/calendar_month/block_calendar_month.php @@ -10,7 +10,7 @@ function preferred_width() { } function get_content() { - global $USER, $CFG, $SESSION; + global $USER, $CFG, $SESSION, $COURSE, $OUTPUT; $cal_m = optional_param( 'cal_m', 0, PARAM_INT ); $cal_y = optional_param( 'cal_y', 0, PARAM_INT ); @@ -51,6 +51,45 @@ function get_content() { $this->content->text .= '
'.calendar_filter_controls($this->page->url).'
'; } + // MDL-18375, Multi-Calendar Support + if (empty($COURSE->calendarsystem)) { + // the course has not a forced calendarsystem + // so user can change it. + $url = $CFG->wwwroot . (!empty($COURSE->id) && ($COURSE->id!= SITEID) ? "/course/view.php?id={$COURSE->id}" : '/index.php'); + $url = new moodle_url($url); + + $calendarselect = new single_select($url, 'calendarsystem', get_list_of_calendars(), current_calendarsystem_plugin(), false, 'choosecalendar'); + $calendarselect->set_label(''.get_string('system', 'calendarsystem').''); + + $this->content->text .= ' + + ' . $OUTPUT->render($calendarselect) . ' + + '; + } + return $this->content; } } diff --git a/calendar/event.php b/calendar/event.php index 027527bf9dc05..71717a8e15151 100644 --- a/calendar/event.php +++ b/calendar/event.php @@ -133,9 +133,10 @@ unset($formoptions->eventtypes->groups); } } - if($cal_y && $cal_m && $cal_d && checkdate($cal_m, $cal_d, $cal_y)) { + // MDL-18375, Multi-Calendar Support + if($cal_y && $cal_m && $cal_d && $CALENDARSYSTEM->checkdate($cal_m, $cal_d, $cal_y)) { $event->timestart = make_timestamp($cal_y, $cal_m, $cal_d, 0, 0, 0); - } else if($cal_y && $cal_m && checkdate($cal_m, 1, $cal_y)) { + } else if($cal_y && $cal_m && $CALENDARSYSTEM->checkdate($cal_m, 1, $cal_y)) { $now = usergetdate(time()); if($cal_y == $now['year'] && $cal_m == $now['mon']) { $event->timestart = make_timestamp($cal_y, $cal_m, $now['mday'], 0, 0, 0); diff --git a/calendar/export_execute.php b/calendar/export_execute.php index 7cd585bdcf0c5..f5e638a65f67f 100644 --- a/calendar/export_execute.php +++ b/calendar/export_execute.php @@ -34,7 +34,9 @@ $what = optional_param('preset_what', 'all', PARAM_ALPHA); $time = optional_param('preset_time', 'weeknow', PARAM_ALPHA); -$now = usergetdate(time()); +// MDL-18375, Multi-Calendar Support +$calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); +$now = $calendarsystem_gregorian->usergetdate(time()); // Let's see if we have sufficient and correct data $allowed_what = array('all', 'courses'); $allowed_time = array('weeknow', 'weeknext', 'monthnow', 'monthnext', 'recentupcoming', 'custom'); @@ -80,47 +82,47 @@ $startmonthday = find_day_in_month($now['mday'] - 6, $startweekday, $now['mon'], $now['year']); $startmonth = $now['mon']; $startyear = $now['year']; - if($startmonthday > calendar_days_in_month($startmonth, $startyear)) { + if($startmonthday > $calendarsystem_gregorian->calendar_days_in_month($startmonth, $startyear)) { list($startmonth, $startyear) = calendar_add_month($startmonth, $startyear); $startmonthday = find_day_in_month(1, $startweekday, $startmonth, $startyear); } - $timestart = make_timestamp($startyear, $startmonth, $startmonthday); + $timestart = $calendarsystem_gregorian->make_timestamp($startyear, $startmonth, $startmonthday); $endmonthday = $startmonthday + 7; $endmonth = $startmonth; $endyear = $startyear; - if($endmonthday > calendar_days_in_month($endmonth, $endyear)) { + if($endmonthday > $calendarsystem_gregorian->calendar_days_in_month($endmonth, $endyear)) { list($endmonth, $endyear) = calendar_add_month($endmonth, $endyear); $endmonthday = find_day_in_month(1, $startweekday, $endmonth, $endyear); } - $timeend = make_timestamp($endyear, $endmonth, $endmonthday) - 1; + $timeend = $calendarsystem_gregorian->make_timestamp($endyear, $endmonth, $endmonthday) - 1; break; case 'weeknext': $startweekday = get_user_preferences('calendar_startwday', calendar_get_starting_weekday()); $startmonthday = find_day_in_month($now['mday'] + 1, $startweekday, $now['mon'], $now['year']); $startmonth = $now['mon']; $startyear = $now['year']; - if($startmonthday > calendar_days_in_month($startmonth, $startyear)) { + if($startmonthday > $calendarsystem_gregorian->calendar_days_in_month($startmonth, $startyear)) { list($startmonth, $startyear) = calendar_add_month($startmonth, $startyear); $startmonthday = find_day_in_month(1, $startweekday, $startmonth, $startyear); } - $timestart = make_timestamp($startyear, $startmonth, $startmonthday); + $timestart = $calendarsystem_gregorian->make_timestamp($startyear, $startmonth, $startmonthday); $endmonthday = $startmonthday + 7; $endmonth = $startmonth; $endyear = $startyear; - if($endmonthday > calendar_days_in_month($endmonth, $endyear)) { + if($endmonthday > $calendarsystem_gregorian->calendar_days_in_month($endmonth, $endyear)) { list($endmonth, $endyear) = calendar_add_month($endmonth, $endyear); $endmonthday = find_day_in_month(1, $startweekday, $endmonth, $endyear); } - $timeend = make_timestamp($endyear, $endmonth, $endmonthday) - 1; + $timeend = $calendarsystem_gregorian->make_timestamp($endyear, $endmonth, $endmonthday) - 1; break; case 'monthnow': - $timestart = make_timestamp($now['year'], $now['mon'], 1); - $timeend = make_timestamp($now['year'], $now['mon'], calendar_days_in_month($now['mon'], $now['year']), 23, 59, 59); + $timestart = $calendarsystem_gregorian->make_timestamp($now['year'], $now['mon'], 1); + $timeend = $calendarsystem_gregorian->make_timestamp($now['year'], $now['mon'], calendar_days_in_month($now['mon'], $now['year']), 23, 59, 59); break; case 'monthnext': list($nextmonth, $nextyear) = calendar_add_month($now['mon'], $now['year']); - $timestart = make_timestamp($nextyear, $nextmonth, 1); - $timeend = make_timestamp($nextyear, $nextmonth, calendar_days_in_month($nextmonth, $nextyear), 23, 59, 59); + $timestart = $calendarsystem_gregorian->make_timestamp($nextyear, $nextmonth, 1); + $timeend = $calendarsystem_gregorian->make_timestamp($nextyear, $nextmonth, calendar_days_in_month($nextmonth, $nextyear), 23, 59, 59); break; case 'recentupcoming': //Events in the last 5 or next 60 days diff --git a/calendar/lib.php b/calendar/lib.php index ede82803316b5..20f5a8f28e1d5 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -187,6 +187,8 @@ function calendar_get_starting_weekday() { */ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_year = false, $placement = false, $courseid = false ) { global $CFG, $USER, $OUTPUT; + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; $display = new stdClass; $display->minwday = get_user_preferences('calendar_startwday', calendar_get_starting_weekday()); @@ -202,7 +204,7 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y $display->thismonth = true; } else { // Navigated to other month, let's do a nice trick and save us a lot of work... - if(!checkdate($cal_month, 1, $cal_year)) { + if(!$CALENDARSYSTEM->checkdate($cal_month, 1, $cal_year)) { $date = array('mday' => 1, 'mon' => $thisdate['mon'], 'year' => $thisdate['year']); $display->thismonth = true; } else { @@ -221,12 +223,12 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y if (get_user_timezone_offset() < 99) { // We 'll keep these values as GMT here, and offset them when the time comes to query the db - $display->tstart = gmmktime(0, 0, 0, $m, 1, $y); // This is GMT - $display->tend = gmmktime(23, 59, 59, $m, $display->maxdays, $y); // GMT + $display->tstart = $CALENDARSYSTEM->gmmktime(0, 0, 0, $m, 1, $y); // This is GMT + $display->tend = $CALENDARSYSTEM->gmmktime(23, 59, 59, $m, $display->maxdays, $y); // GMT } else { // no timezone info specified - $display->tstart = mktime(0, 0, 0, $m, 1, $y); - $display->tend = mktime(23, 59, 59, $m, $display->maxdays, $y); + $display->tstart = $CALENDARSYSTEM->mktime(0, 0, 0, $m, 1, $y); + $display->tend = $CALENDARSYSTEM->mktime(23, 59, 59, $m, $display->maxdays, $y); } $startwday = dayofweek(1, $m, $y); @@ -824,6 +826,8 @@ function calendar_get_events_by_id($eventids) { */ function calendar_top_controls($type, $data) { global $CFG, $PAGE; + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; $content = ''; if(!isset($data['d'])) { $data['d'] = 1; @@ -836,11 +840,11 @@ function calendar_top_controls($type, $data) { $courseid = '&course='.$data['id']; } - if(!checkdate($data['m'], $data['d'], $data['y'])) { + if(!$CALENDARSYSTEM->checkdate($data['m'], $data['d'], $data['y'])) { $time = time(); } else { - $time = make_timestamp($data['y'], $data['m'], $data['d']); + $time = $CALENDARSYSTEM->make_timestamp($data['y'], $data['m'], $data['d']); } $date = usergetdate($time); @@ -1210,7 +1214,9 @@ function calendar_wday_name($englishname) { * @return int */ function calendar_days_in_month($month, $year) { - return intval(date('t', mktime(0, 0, 0, $month, 1, $year))); + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; + return $CALENDARSYSTEM->calendar_days_in_month($month, $year); } /** @@ -1733,10 +1739,11 @@ function calendar_format_event_time($event, $now, $linkparams = null, $usecommon * @param string|array $selected options for select elements */ function calendar_print_month_selector($name, $selected) { - $months = array(); - for ($i=1; $i<=12; $i++) { - $months[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), '%B'); - } + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; + + $months = $CALENDARSYSTEM->get_month_names(); + echo html_writer::label(get_string('months'), 'menu'. $name, false, array('class' => 'accesshide')); echo html_writer::select($months, $name, $selected, false); } diff --git a/calendar/renderer.php b/calendar/renderer.php index 4fc9a05d76c33..1e05d89b463fe 100644 --- a/calendar/renderer.php +++ b/calendar/renderer.php @@ -380,6 +380,8 @@ public function event(calendar_event $event, $showactions=true) { */ public function show_month_detailed(calendar_information $calendar, moodle_url $returnurl = null) { global $CFG; + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; if (empty($returnurl)) { $returnurl = $this->page->url; @@ -396,13 +398,13 @@ public function show_month_detailed(calendar_information $calendar, moodle_url $ $startwday = 0; if (get_user_timezone_offset() < 99) { // We 'll keep these values as GMT here, and offset them when the time comes to query the db - $display->tstart = gmmktime(0, 0, 0, $calendar->month, 1, $calendar->year); // This is GMT - $display->tend = gmmktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); // GMT + $display->tstart = $CALENDARSYSTEM->gmmktime(0, 0, 0, $calendar->month, 1, $calendar->year); // This is GMT + $display->tend = $CALENDARSYSTEM->gmmktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); // GMT $startwday = gmdate('w', $display->tstart); // $display->tstart is already GMT, so don't use date(): messes with server's TZ } else { // no timezone info specified - $display->tstart = mktime(0, 0, 0, $calendar->month, 1, $calendar->year); - $display->tend = mktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); + $display->tstart = $CALENDARSYSTEM->mktime(0, 0, 0, $calendar->month, 1, $calendar->year); + $display->tend = $CALENDARSYSTEM->mktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); $startwday = date('w', $display->tstart); // $display->tstart not necessarily GMT, so use date() } diff --git a/calendar/view.php b/calendar/view.php index 40a2d82a13541..8995f6d395002 100644 --- a/calendar/view.php +++ b/calendar/view.php @@ -88,7 +88,8 @@ $strcalendar = get_string('calendar', 'calendar'); -if (!checkdate($mon, $day, $yr)) { +// MDL-18375, Multi-Calendar Support +if (!$CALENDARSYSTEM->checkdate($mon, $day, $yr)) { $day = intval($now['mday']); $mon = intval($now['mon']); $yr = intval($now['year']); diff --git a/calendarsystem/admin.php b/calendarsystem/admin.php new file mode 100644 index 0000000000000..f32981a6d1cbb --- /dev/null +++ b/calendarsystem/admin.php @@ -0,0 +1,98 @@ +. + +require_once('../config.php'); +require_once($CFG->libdir.'/adminlib.php'); +require_once($CFG->libdir.'/tablelib.php'); + +admin_externalpage_setup('managecalendarsystems'); + +$delete = optional_param('delete', '', PARAM_PLUGIN); +$confirm = optional_param('confirm', '', PARAM_BOOL); + +/// If data submitted, then process and store. + +if (!empty($delete) and confirm_sesskey()) { + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('type_calendarsystem_plural', 'plugin')); + + if (!$confirm) { + if (get_string_manager()->string_exists('pluginname', 'calendarsystem_' . $delete)) { + $strpluginname = get_string('pluginname', 'calendarsystem_' . $delete); + } else { + $strpluginname = $delete; + } + echo $OUTPUT->confirm(get_string('calendarsystemdeleteconfirm', 'calendarsystem', $strpluginname), + new moodle_url($PAGE->url, array('delete' => $delete, 'confirm' => 1)), + $PAGE->url); + echo $OUTPUT->footer(); + die(); + + } else { + uninstall_plugin('calendarsystem', $delete); + $a = new stdclass(); + $a->name = $delete; + $pluginlocation = get_plugin_types(); + $a->directory = $pluginlocation['calendarsystem'] . '/' . $delete; + echo $OUTPUT->notification(get_string('plugindeletefiles', '', $a), 'notifysuccess'); + echo $OUTPUT->continue_button($PAGE->url); + echo $OUTPUT->footer(); + die(); + } +} + +echo $OUTPUT->header(); +echo $OUTPUT->heading(get_string('type_calendarsystem_plural', 'plugin')); + +/// Print the table of all installed local plugins + +$table = new flexible_table('calendarsystems_administration_table'); +$table->define_columns(array('name', 'version', 'delete')); +$table->define_headers(array(get_string('plugin'), get_string('version'), get_string('delete'))); +$table->define_baseurl($PAGE->url); +$table->set_attribute('id', 'calendarsystems'); +$table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide'); +$table->setup(); + +$plugins = array(); +foreach (get_plugin_list('calendarsystem') as $plugin => $plugindir) { + if (get_string_manager()->string_exists('pluginname', 'calendarsystem_' . $plugin)) { + $strpluginname = get_string('pluginname', 'calendarsystem_' . $plugin); + } else { + $strpluginname = $plugin; + } + $plugins[$plugin] = $strpluginname; +} +collatorlib::asort($plugins); + +foreach ($plugins as $plugin => $name) { + $delete = new moodle_url($PAGE->url, array('delete' => $plugin, 'sesskey' => sesskey())); + $delete = html_writer::link($delete, get_string('delete')); + + $version = get_config('calendarsystem_' . $plugin); + if (!empty($version->version)) { + $version = $version->version; + } else { + $version = '?'; + } + + $table->add_data(array($name, $version, $delete)); +} + +$table->print_html(); +echo $OUTPUT->container(html_writer::link('index.php', get_string('checkforupdates', 'calendarsystem')), 'singlebutton'); +echo $OUTPUT->footer(); diff --git a/calendarsystem/calendarsystem.class.php b/calendarsystem/calendarsystem.class.php new file mode 100644 index 0000000000000..cea0f3839db06 --- /dev/null +++ b/calendarsystem/calendarsystem.class.php @@ -0,0 +1,69 @@ +calendarsystem) ? 'gregorian' : $CFG->calendarsystem; // we might be in the installation process and $CFG->calendarststem might be undefined yet + } + if (file_exists("$CFG->dirroot/calendarsystem/$system/calendarsystem.php")) { + require_once("$CFG->dirroot/calendarsystem/$system/calendarsystem.php"); + $class = "calendarsystem_plugin_$system"; + return new $class; + } else { + trigger_error("$CFG->dirroot/calendarsystem/$system/calendarsystem.php does not exist"); + notify("Calendar system file $system/calendarsystem.php does not exist"); + } + } +} + +function get_list_of_calendars() { + $calendars = array(); + $calendardirs = get_list_of_plugins('calendarsystem'); + + foreach ($calendardirs as $calendar) { + $calendars[$calendar] = get_string('name', "calendarsystem_{$calendar}"); + } + + return $calendars; +} + +function current_calendarsystem_plugin() { + global $CFG, $USER, $SESSION, $COURSE; + + if (!empty($COURSE->id) and $COURSE->id != SITEID and !empty($COURSE->calendarsystem)) { // Course calendarsystem can override all other settings for this page + $return = $COURSE->calendarsystem; + + } else if (!empty($SESSION->calendarsystem)) { // Session calendarsystem can override other settings + $return = $SESSION->calendarsystem; + + } else if (!empty($USER->calendarsystem)) { + $return = $USER->calendarsystem; + + } else { + $return = $CFG->calendarsystem; + } + + return $return; +} +?> \ No newline at end of file diff --git a/calendarsystem/gregorian/calendarsystem.php b/calendarsystem/gregorian/calendarsystem.php new file mode 100644 index 0000000000000..bfe480524200f --- /dev/null +++ b/calendarsystem/gregorian/calendarsystem.php @@ -0,0 +1,88 @@ + \ No newline at end of file diff --git a/calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php b/calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php new file mode 100644 index 0000000000000..c0df03a3f48e8 --- /dev/null +++ b/calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php b/calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php new file mode 100644 index 0000000000000..2cb6e5f6aed74 --- /dev/null +++ b/calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/calendarsystem/gregorian/version.php b/calendarsystem/gregorian/version.php new file mode 100644 index 0000000000000..ae02452791356 --- /dev/null +++ b/calendarsystem/gregorian/version.php @@ -0,0 +1,31 @@ +. + +/** + * Version details + * + * @package calendarsystem + * @subpackage gregorian + * @author Shamim Rezaie + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) +$plugin->requires = 2012120300; // Requires this Moodle version +$plugin->component = 'calendarsystem_gregorian'; // Full name of the plugin (used for diagnostics) diff --git a/calendarsystem/hijri/calendarsystem.php b/calendarsystem/hijri/calendarsystem.php new file mode 100644 index 0000000000000..54ea267cf6aab --- /dev/null +++ b/calendarsystem/hijri/calendarsystem.php @@ -0,0 +1,250 @@ +to_gregorian(1, $m+1, $y); + $temp = $this->from_gregorian($temp['day']-1, $temp['month'], $temp['year']); + return $temp['day']; + } + + public function usergetdate($time, $timezone=99) { + $date = usergetdate_old($time); + $new_date = $this->from_gregorian($date["mday"], $date["mon"], $date["year"]); + + $date["month"] = get_string("month{$new_date['month']}", 'calendarsystem_hijri'); + $date["weekday"] = get_string("weekday{$date['wday']}", 'calendarsystem_hijri'); + $date["yday"] = null; + $date["year"] = $new_date['year']; + $date["mon"] = $new_date['month']; + $date["mday"] = $new_date['day']; + + return $date; + } + + public function checkdate($m, $d, $y) + { + $temp = $this->to_gregorian($d, $m, $y); + $temp = $this->from_gregorian($temp['day'], $temp['month'], $temp['year']); + return ($temp['day'] == $d) && ($temp['month'] == $m) && ($temp['year'] == $y); + } + + public function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { + $new_date = $this->to_gregorian($day, $month, $year); + return make_timestamp_old($new_date['year'], $new_date['month'], $new_date['day'], $hour, $minute, $second, $timezone, $applydst); + } + + public function userdate($date, $format='', $timezone=99, $fixday = true, $fixhour = true) { + static $amstring = null, $pmstring = null, $AMstring = null, $PMstring = null; + + if (!$amstring) { + $amstring = get_string('am', 'calendarsystem_hijri'); + $pmstring = get_string('pm', 'calendarsystem_hijri'); + $AMstring = get_string('am_caps', 'calendarsystem_hijri'); + $PMstring = get_string('pm_caps', 'calendarsystem_hijri'); + } + + if (empty($format)) { + $format = get_string('strftimedaydatetime'); + } + + if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed. + $fixday = false; + } + + $date_ = $this->usergetdate($date); + //this is not sufficient code, change it. but it works correctly. + $format = str_replace( array( + "%a", + "%A", + "%b", + "%B", + "%d", + "%m", + "%y", + "%Y", + "%p", + "%P" + ), + array( + $date_["weekday"], + $date_["weekday"], + $date_["month"], + $date_["month"], + (($date_["mday"] < 10 && !$fixday) ? '0' : '') . $date_["mday"], + ($date_["mon"] < 10 ? '0' : '') . $date_["mon"], + $date_["year"] % 100, + $date_["year"], + ($date_["hours"] < 12 ? $AMstring : $PMstring), + ($date_["hours"] < 12 ? $amstring : $pmstring) + ), + $format); + + return userdate_old($date, $format, $timezone, $fixday, $fixhour); + } + + public function today() + { + list($g_y, $g_m, $g_d) = explode( "-", date("Y-m-d")); + $today = $this->from_gregorian((int)$g_d, (int)$g_m, (int)$g_y); + + return array($today['month'], $today['day'], $today['year']); + } + + public function get_month_names() + { + $months = array(); + + for ($i=1; $i<=12; $i++) { + $months[$i] = get_string("month{$i}", 'calendarsystem_hijri'); + } + + return $months; + } + + public function get_min_year() + { + return 1390; + } + + public function get_max_year() + { + return 1440; + } + + public function gmmktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { + if (empty($day) || empty($month) || empty($year)) { + $today = $this->today(); + if (empty($day)) { + $day = $today['day']; + } + if (empty($month)) { + $month = $today['month']; + } + if (empty($year)) { + $year = $today['year']; + } + } + + $g_date = $this->to_gregorian($day, $month, $year); + + return gmmktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); + } + + public function mktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { + if (empty($day) || empty($month) || empty($year)) { + $today = $this->today(); + + if (empty($day)) { + $day = $today['day']; + } + if (empty($month)) { + $month = $today['month']; + } + if (empty($year)) { + $year = $today['year']; + } + } + + $g_date = $this->to_gregorian($day, $month, $year); + + return mktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); + } + + public function dayofweek($day, $month, $year) { + $g_date = $this->to_gregorian($day, $month, $year); + return intval(date('w', mktime(12, 0, 0, $g_date['month'], $g_date['day'], $g_date['year']))); + } + + private $ISLAMIC_EPOCH = 1948439.5; + private $GREGORIAN_EPOCH = 1721425.5; + + // LEAP_GREGORIAN -- Is a given year in the Gregorian calendar a leap year ? + private function leap_gregorian($year) + { + return (($year % 4) == 0) && + (!((($year % 100) == 0) && (($year % 400) != 0))); + } + + // GREGORIAN_TO_JD -- Determine Julian day number from Gregorian calendar date + private function gregorian_to_jd($year, $month, $day) + { + return ($this->GREGORIAN_EPOCH - 1) + + (365 * ($year - 1)) + + floor(($year - 1) / 4) + + (-floor(($year - 1) / 100)) + + floor(($year - 1) / 400) + + floor((((367 * $month) - 362) / 12) + + (($month <= 2) ? 0 : ($this->leap_gregorian($year) ? -1 : -2) + ) + + $day); + } + + // JD_TO_GREGORIAN -- Calculate Gregorian calendar date from Julian day + private function jd_to_gregorian($jd) { + $wjd = floor($jd - 0.5) + 0.5; + $depoch = $wjd - $this->GREGORIAN_EPOCH; + $quadricent = floor($depoch / 146097); + $dqc = $depoch % 146097; + $cent = floor($dqc / 36524); + $dcent = $dqc % 36524; + $quad = floor($dcent / 1461); + $dquad = $dcent % 1461; + $yindex = floor($dquad / 365); + $year = ($quadricent * 400) + ($cent * 100) + ($quad * 4) + $yindex; + if (!(($cent == 4) || ($yindex == 4))) { + $year++; + } + $yearday = $wjd - $this->gregorian_to_jd($year, 1, 1); + $leapadj = (($wjd < $this->gregorian_to_jd($year, 3, 1)) ? 0 : ($this->leap_gregorian($year) ? 1 : 2)); + $month = floor(((($yearday + $leapadj) * 12) + 373) / 367); + $day = ($wjd - $this->gregorian_to_jd($year, $month, 1)) + 1; + + return array('year' => $year, + 'month' => $month, + 'day' => $day); + } + + + private function islamic_to_jd($year, $month, $day) + { + return ($day + + ceil(29.5 * ($month - 1)) + + ($year - 1) * 354 + + floor((3 + (11 * $year)) / 30) + + $this->ISLAMIC_EPOCH) - 1; + } + + + + // JD_TO_ISLAMIC -- Calculate Islamic date from Julian day + private function jd_to_islamic($jd) + { + $jd = floor($jd) + 0.5; + $year = floor(((30 * ($jd - $this->ISLAMIC_EPOCH)) + 10646) / 10631); + $month = min(12, + ceil(($jd - (29 + $this->islamic_to_jd($year, 1, 1))) / 29.5) + 1); + $day = ($jd - $this->islamic_to_jd($year, $month, 1)) + 1; + + return array('year' => $year, + 'month' => $month, + 'day' => $day); + } + + private function from_gregorian($g_d, $g_m, $g_y) { + $jd = $this->gregorian_to_jd($g_y, $g_m, $g_d); + return $this->jd_to_islamic($jd); + } + + private function to_gregorian($i_d, $i_m, $i_y) { + $jd = $this->islamic_to_jd($i_y, $i_m, $i_d); + return $this->jd_to_gregorian($jd); + } +} +?> \ No newline at end of file diff --git a/calendarsystem/hijri/lang/en/calendarsystem_hijri.php b/calendarsystem/hijri/lang/en/calendarsystem_hijri.php new file mode 100644 index 0000000000000..04f02d017fdde --- /dev/null +++ b/calendarsystem/hijri/lang/en/calendarsystem_hijri.php @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/calendarsystem/hijri/lang/fa/calendarsystem_hijri.php b/calendarsystem/hijri/lang/fa/calendarsystem_hijri.php new file mode 100644 index 0000000000000..233d14979a229 --- /dev/null +++ b/calendarsystem/hijri/lang/fa/calendarsystem_hijri.php @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/calendarsystem/hijri/version.php b/calendarsystem/hijri/version.php new file mode 100644 index 0000000000000..64024e6739a2c --- /dev/null +++ b/calendarsystem/hijri/version.php @@ -0,0 +1,31 @@ +. + +/** + * Version details + * + * @package calendarsystem + * @subpackage hijri + * @author Shamim Rezaie + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) +$plugin->requires = 2012120300; // Requires this Moodle version +$plugin->component = 'calendarsystem_hijri'; // Full name of the plugin (used for diagnostics) diff --git a/calendarsystem/index.php b/calendarsystem/index.php new file mode 100644 index 0000000000000..839795664be95 --- /dev/null +++ b/calendarsystem/index.php @@ -0,0 +1,175 @@ +libdir.'/adminlib.php'); // various admin-only functions +require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions +require_once($CFG->libdir.'/pluginlib.php'); // available updates notifications +require_once('updatechecker.php'); // available updates notifications + +$fetchupdates = optional_param('fetchupdates', 0, PARAM_BOOL); + +// Check some PHP server settings + +$PAGE->set_url('/calendarsystem/index.php'); +$PAGE->set_pagelayout('admin'); // Set a default pagelayout + +$version = null; +require("$CFG->dirroot/calendarsystem/version.php"); +// Check version of calendarsystem code on disk + +$PAGE->set_context(context_system::instance()); + +// Check for valid admin user - no guest autologin +require_login(0, false); +$context = context_system::instance(); +require_capability('moodle/site:config', $context); + + +// Everything should now be set up, and the user is an admin + + +// Available updates for Moodle core +$updateschecker = calendarsystem_update_checker::instance(); +$availableupdates = array(); +$availableupdates['core'] = $updateschecker->get_update_info('core'); + +// Available updates for calendar system plugins +$calendars = get_plugin_list('calendarsystem'); +foreach ($calendars as $calendar => $calendarrootdir) { + $availableupdates[$calendar] = $updateschecker->get_update_info('calendarsystem_'.$calendar); +} +/* +$pluginman = plugin_manager::instance(); +foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) { + foreach ($plugintypeinstances as $pluginname => $plugininfo) { + if (!empty($plugininfo->availableupdates)) { + foreach ($plugininfo->availableupdates as $pluginavailableupdate) { + if ($pluginavailableupdate->version > $plugininfo->versiondisk) { + if (!isset($availableupdates[$plugintype.'_'.$pluginname])) { + $availableupdates[$plugintype.'_'.$pluginname] = array(); + } + $availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate; + } + } + } + } +} +*/ +// The timestamp of the most recent check for available updates +$availableupdatesfetch = $updateschecker->get_last_timefetched(); + +//admin_externalpage_setup('adminnotifications'); + +if ($fetchupdates) { + require_sesskey(); + $updateschecker->fetch(); + redirect($PAGE->url); +} + +$strupdatecheck = get_string('updatecheck', 'calendarsystem'); +$PAGE->navbar->add($strupdatecheck); + +echo $OUTPUT->header(); +echo available_updates($availableupdates, $availableupdatesfetch); + +echo $OUTPUT->footer(); + + +/////////////////////////////////////////////////////////////////////////////////////// + /** + * Displays the info about available Moodle core and plugin updates + * + * The structure of the $updates param has changed since 2.4. It contains not only updates + * for the core itself, but also for all other installed plugins. + * + * @param array|null $updates array of (string)component => array of calendarsystem_update_info objects or null + * @param int|null $fetch timestamp of the most recent updates fetch or null (unknown) + * @return string + */ + function available_updates($updates, $fetch) { + global $OUTPUT; + + $updateinfo = $OUTPUT->box_start('generalbox adminwarning calendarsystemupdatesinfo'); + $someupdateavailable = false; + if (is_array($updates)) { + if (is_array($updates['core'])) { + $someupdateavailable = true; + $updateinfo .= $OUTPUT->heading(get_string('updateavailable', 'calendarsystem'), 3); + foreach ($updates['core'] as $update) { + $updateinfo .= moodle_available_update_info($update); + } + } + unset($updates['core']); + // If something has left in the $updates array now, it is updates for plugins. + if (!empty($updates)) { + foreach ($updates as $pluginname=>$pluginupdates) { + if (is_array($pluginupdates)) { + $someupdateavailable = true; + $updateinfo .= $OUTPUT->heading(get_string('updateavailableforplugin', 'calendarsystem', get_string('name', 'calendarsystem_'.$pluginname)), 3); + + foreach ($pluginupdates as $update) { + $updateinfo .= moodle_available_update_info($update); + } + } + } + } + } + + if (!$someupdateavailable) { + $now = time(); + if ($fetch and ($fetch <= $now) and ($now - $fetch < HOURSECS)) { + $updateinfo .= $OUTPUT->heading(get_string('updateavailablenot', 'calendarsystem'), 3); + } + } + + $updateinfo .= $OUTPUT->container_start('checkforupdates'); + $updateinfo .= $OUTPUT->single_button(new moodle_url('', array('fetchupdates' => 1)), get_string('checkforupdates', 'calendarsystem')); + if ($fetch) { + $updateinfo .= $OUTPUT->container(get_string('checkforupdateslast', 'core_plugin', + userdate($fetch, get_string('strftimedatetime', 'core_langconfig')))); + } + $updateinfo .= $OUTPUT->container_end(); + + $updateinfo .= $OUTPUT->box_end(); + + return $updateinfo; + } + + + /** + * Helper method to render the information about the available Moodle update + * + * @param calendarsystem_update_info $updateinfo information about the available Moodle core update + */ + function moodle_available_update_info(calendarsystem_update_info $updateinfo) { + global $OUTPUT; + + $boxclasses = 'moodleupdateinfo'; + $info = array(); + + if (isset($updateinfo->version)) { + $info[] = html_writer::tag('span', get_string('updateavailable_version', 'calendarsystem', $updateinfo->version), + array('class' => 'info version')); + } + + if (isset($updateinfo->download)) { + $info[] = html_writer::link($updateinfo->download, get_string('download'), array('class' => 'info download')); + } + + if (isset($updateinfo->url)) { + $info[] = html_writer::link($updateinfo->url, get_string('updateavailable_moreinfo', 'calendarsystem'), + array('class' => 'info more')); + } + + $box = $OUTPUT->box_start($boxclasses); + $box .= $OUTPUT->box(implode(html_writer::tag('span', ' - ', array('class' => 'separator')), $info), ''); + $box .= $OUTPUT->box_end(); + + return $box; + } +/////////////////////////////////////////////////////////////////////////////////////// + + + diff --git a/calendarsystem/jalali/calendarsystem.php b/calendarsystem/jalali/calendarsystem.php new file mode 100644 index 0000000000000..dd5e435398df8 --- /dev/null +++ b/calendarsystem/jalali/calendarsystem.php @@ -0,0 +1,289 @@ +isleap_solar($y)) + return 30; + + return 29; + } + + public function usergetdate($time, $timezone=99) { + $date = usergetdate_old($time); + $new_date = $this->from_gregorian($date["mday"], $date["mon"], $date["year"]); + + $date["month"] = get_string("month{$new_date['month']}", 'calendarsystem_jalali'); + $date["weekday"] = get_string("weekday{$date['wday']}", 'calendarsystem_jalali'); + $date["yday"] = null; + $date["year"] = $new_date['year']; + $date["mon"] = $new_date['month']; + $date["mday"] = $new_date['day']; + + return $date; +} + + public function checkdate($m, $d, $y) + { + // $m not in 1..12 or $d not in 1..31 + if ($m < 1 or 12 < $m or $d < 1 or $d > 31) + return false; + + // $m in 1..6 and at this line $d in 1..31 + if ($m < 7) + return true; + + // $m in 7..11 and possible value for $d is in 0..31 (but 31 is invalid) + if ($m != 12) + if ($d == 31) { + return false; + } else { + return true; + } + + // $m is 12 + if ($this->isleap_solar($y)) + { + if ($d == 31) + return false; + } + else // $y is not leap year. + if ($d == 31) + return false; + + return true; + } + + public function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { + $new_date = $this->to_gregorian($day, $month, $year); + return make_timestamp_old($new_date['year'], $new_date['month'], $new_date['day'], $hour, $minute, $second, $timezone, $applydst); + } + + public function userdate($date, $format='', $timezone=99, $fixday = true, $fixhour = true) { + static $amstring = null, $pmstring = null, $AMstring = null, $PMstring = null; + + if (!$amstring) { + $amstring = get_string('am', 'calendarsystem_jalali'); + $pmstring = get_string('pm', 'calendarsystem_jalali'); + $AMstring = get_string('am_caps', 'calendarsystem_jalali'); + $PMstring = get_string('pm_caps', 'calendarsystem_jalali'); + } + + if (empty($format)) { + $format = get_string('strftimedaydatetime'); + } + + if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed. + $fixday = false; + } + + $date_ = $this->usergetdate($date); + //this is not sufficient code, change it. but it works correctly. + $format = str_replace( array( + "%a", + "%A", + "%b", + "%B", + "%d", + "%m", + "%y", + "%Y", + "%p", + "%P" + ), + array( + $date_["weekday"], + $date_["weekday"], + $date_["month"], + $date_["month"], + (($date_["mday"] < 10 && !$fixday) ? '0' : '') . $date_["mday"], + ($date_["mon"] < 10 ? '0' : '') . $date_["mon"], + $date_["year"] % 100, + $date_["year"], + ($date_["hours"] < 12 ? $AMstring : $PMstring), + ($date_["hours"] < 12 ? $amstring : $pmstring) + ), + $format); + + return userdate_old($date, $format, $timezone, $fixday, $fixhour); + } + + public function today() + { + list($g_y, $g_m, $g_d) = explode( "-", date("Y-m-d")); + $today = $this->from_gregorian((int)$g_d, (int)$g_m, (int)$g_y); + + return array($today['month'], $today['day'], $today['year']); + } + + public function get_month_names() + { + $months = array(); + + for ($i=1; $i<=12; $i++) { + $months[$i] = get_string("month{$i}", 'calendarsystem_jalali'); + } + + return $months; + } + + public function get_min_year() + { + return 1350; + } + + public function get_max_year() + { + return 1400; + } + + public function gmmktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { + if (empty($day) || empty($month) || empty($year)) { + $today = $this->today(); + if (empty($day)) { + $day = $today['day']; + } + if (empty($month)) { + $month = $today['month']; + } + if (empty($year)) { + $year = $today['year']; + } + } + + $g_date = $this->to_gregorian($day, $month, $year); + + return gmmktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); + } + + public function mktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { + if (empty($day) || empty($month) || empty($year)) { + $today = $this->today(); + + if (empty($day)) { + $day = $today['day']; + } + if (empty($month)) { + $month = $today['month']; + } + if (empty($year)) { + $year = $today['year']; + } + } + + $g_date = $this->to_gregorian($day, $month, $year); + + return mktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); + } + + public function dayofweek($day, $month, $year) { + $g_date = $this->to_gregorian($day, $month, $year); + return intval(date('w', mktime(12, 0, 0, $g_date['month'], $g_date['day'], $g_date['year']))); + } + + + private $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); + private $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29); + + private function isleap_solar($year) { + /* 33-year cycles, it better matches Iranian rules */ + return (($year+16)%33+33)%33*8%33 < 8; + } + + private function from_gregorian($g_d, $g_m, $g_y) { + $gy = $g_y-1600; + $gm = $g_m-1; + $gd = $g_d-1; + + $g_day_no = 365*$gy+$this->div($gy+3,4)-$this->div($gy+99,100)+$this->div($gy+399,400); + + for ($i=0; $i < $gm; ++$i) + $g_day_no += $this->g_days_in_month[$i]; + if ($gm>1 && (($gy%4==0 && $gy%100!=0) || ($gy%400==0))) + /* leap and after Feb */ + ++$g_day_no; + $g_day_no += $gd; + + $j_day_no = $g_day_no-79; + + $j_np = $this->div($j_day_no, 12053); + $j_day_no %= 12053; + + $jy = 979+33*$j_np+4*$this->div($j_day_no,1461); + + $j_day_no %= 1461; + + if ($j_day_no >= 366) { + $jy += $this->div($j_day_no-1, 365); + $j_day_no = ($j_day_no-1)%365; + } + + for ($i = 0; $i < 11 && $j_day_no >= $this->j_days_in_month[$i]; ++$i) { + $j_day_no -= $this->j_days_in_month[$i]; + } + $jm = $i+1; + $jd = $j_day_no+1; + + + return array('year' => $jy, + 'month' => $jm, + 'day' => $jd); + } + + private function to_gregorian($j_d, $j_m, $j_y) { + $jy = $j_y-979; + $jm = $j_m-1; + $jd = $j_d-1; + + $j_day_no = 365*$jy + $this->div($jy, 33)*8 + $this->div($jy%33+3, 4); + for ($i=0; $i < $jm; ++$i) + $j_day_no += $this->j_days_in_month[$i]; + + $j_day_no += $jd; + + $g_day_no = $j_day_no+79; + + $gy = 1600 + 400*$this->div($g_day_no, 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */ + $g_day_no = $g_day_no % 146097; + + $leap = true; + if ($g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */ + { + $g_day_no--; + $gy += 100*$this->div($g_day_no, 36524); /* 36524 = 365*100 + 100/4 - 100/100 */ + $g_day_no = $g_day_no % 36524; + + if ($g_day_no >= 365) + $g_day_no++; + else + $leap = false; + } + + $gy += 4*$this->div($g_day_no, 1461); /* 1461 = 365*4 + 4/4 */ + $g_day_no %= 1461; + + if ($g_day_no >= 366) { + $leap = false; + + $g_day_no--; + $gy += $this->div($g_day_no, 365); + $g_day_no = $g_day_no % 365; + } + + for ($i = 0; $g_day_no >= $this->g_days_in_month[$i] + ($i == 1 && $leap); $i++) + $g_day_no -= $this->g_days_in_month[$i] + ($i == 1 && $leap); + $gm = $i+1; + $gd = $g_day_no+1; + + return array('year' => $gy, + 'month' => $gm, + 'day' => $gd); + } + + private function div($a,$b) { + return (int) ($a / $b); + } +} +?> \ No newline at end of file diff --git a/calendarsystem/jalali/lang/en/calendarsystem_jalali.php b/calendarsystem/jalali/lang/en/calendarsystem_jalali.php new file mode 100644 index 0000000000000..64a7a86cef14a --- /dev/null +++ b/calendarsystem/jalali/lang/en/calendarsystem_jalali.php @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/calendarsystem/jalali/lang/fa/calendarsystem_jalali.php b/calendarsystem/jalali/lang/fa/calendarsystem_jalali.php new file mode 100644 index 0000000000000..35d662c7c9fcf --- /dev/null +++ b/calendarsystem/jalali/lang/fa/calendarsystem_jalali.php @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/calendarsystem/jalali/version.php b/calendarsystem/jalali/version.php new file mode 100644 index 0000000000000..bb397749d6495 --- /dev/null +++ b/calendarsystem/jalali/version.php @@ -0,0 +1,31 @@ +. + +/** + * Version details + * + * @package calendarsystem + * @subpackage jalali + * @author Shamim Rezaie + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) +$plugin->requires = 2012120300; // Requires this Moodle version +$plugin->component = 'calendarsystem_jalali'; // Full name of the plugin (used for diagnostics) diff --git a/calendarsystem/updatechecker.php b/calendarsystem/updatechecker.php new file mode 100644 index 0000000000000..cc6b69da3c990 --- /dev/null +++ b/calendarsystem/updatechecker.php @@ -0,0 +1,341 @@ + (string)version list of additional plugins deployed at this site */ + protected $currentplugins = array(); + + /** + * Direct initiation not allowed, use the factory method {@link self::instance()} + */ + protected function __construct() { + } + + /** + * Sorry, this is singleton + */ + protected function __clone() { + } + + /** + * Factory method for this class + * + * @return calendarsystem_update_checker the singleton instance + */ + public static function instance() { + if (is_null(self::$singletoninstance)) { + self::$singletoninstance = new self(); + } + return self::$singletoninstance; + } + + /** + * Returns the timestamp of the last execution of {@link fetch()} + * + * @return int|null null if it has never been executed or we don't known + */ + public function get_last_timefetched() { + + $this->restore_response(); + + if (!empty($this->recentfetch)) { + return $this->recentfetch; + + } else { + return null; + } + } + + /** + * Fetches the available update status from the remote site + * + * @throws available_update_checker_exception + */ + public function fetch() { + $response = $this->get_response(); + $this->validate_response($response); + $this->store_response($response); + } + + /** + * Returns the available update information for the given component + * + * This method returns null if the most recent response does not contain any information + * about it. The returned structure is an array of available updates for the given + * component. Each update info is an object with at least one property called + * 'version'. Other possible properties are 'release', 'maturity', 'url' and 'downloadurl'. + * + * For the 'core' component, the method returns real updates only (those with higher version). + * For all other components, the list of all known remote updates is returned and the caller + * (usually the {@link plugin_manager}) is supposed to make the actual comparison of versions. + * + * @param string $component frankenstyle + * @param array $options with supported keys 'minmaturity' and/or 'notifybuilds' + * @return null|array null or array of calendarsystem_update_info objects + */ + public function get_update_info($component, array $options = array()) { + + if ($component == 'core') { + $this->load_current_environment(); + } + + $this->restore_response(); + + if (empty($this->recentresponse['updates'][$component])) { + return null; + } + + $updates = array(); + foreach ($this->recentresponse['updates'][$component] as $info) { + $update = new calendarsystem_update_info($component, $info); + if ($update->version <= $this->currentversion) { + continue; + } + $updates[] = $update; + } + + if (empty($updates)) { + return null; + } + + return $updates; + } + + /** + * Makes cURL request to get data from the remote site + * + * @return string raw request result + * @throws calendarsystem_update_checker_exception + */ + protected function get_response() { + global $CFG; + require_once($CFG->libdir.'/filelib.php'); + + $curl = new curl(array('proxy' => true)); + $response = $curl->post($this->prepare_request_url(), $this->prepare_request_params()); + $curlerrno = $curl->get_errno(); + if (!empty($curlerrno)) { + throw new calendarsystem_update_checker_exception('err_response_curl', 'cURL error '.$curlerrno.': '.$curl->error); + } + $curlinfo = $curl->get_info(); + if ($curlinfo['http_code'] != 200) { + throw new calendarsystem_update_checker_exception('err_response_http_code', $curlinfo['http_code']); + } + return $response; + } + +/////////////////////////// +// ino ezafe karde boodam + /** + * Makes sure the response is valid, has correct API format etc. + * + * @param string $response raw response as returned by the {@link self::get_response()} + * @throws calendarsystem_update_checker_exception + */ + protected function validate_response($response) { + + $response = $this->decode_response($response); + + if (empty($response)) { + throw new calendarsystem_update_checker_exception('err_response_empty'); + } + + if (empty($response['status']) or $response['status'] !== 'OK') { + throw new calendarsystem_update_checker_exception('err_response_status', $response['status']); + } + } + + /* Decodes the raw string response from the update notifications provider + * + * @param string $response as returned by {@link self::get_response()} + * @return array decoded response structure + */ + protected function decode_response($response) { + return json_decode($response, true); + } + + /** + * Stores the valid fetched response for later usage + * + * This implementation uses the config_plugins table as the permanent storage. + * + * @param string $response raw valid data returned by {@link self::get_response()} + */ + protected function store_response($response) { + + set_config('recentfetch', time(), 'calendarsystem_plugin'); + set_config('recentresponse', $response, 'calendarsystem_plugin'); + + $this->restore_response(true); + } + + /** + * Loads the most recent raw response record we have fetched + * + * After this method is called, $this->recentresponse is set to an array. If the + * array is empty, then either no data have been fetched yet or the fetched data + * do not have expected format (and thence they are ignored and a debugging + * message is displayed). + * + * This implementation uses the config_plugins table as the permanent storage. + * + * @param bool $forcereload reload even if it was already loaded + */ + protected function restore_response($forcereload = false) { + + if (!$forcereload and !is_null($this->recentresponse)) { + // we already have it, nothing to do + return; + } + + $config = get_config('calendarsystem_plugin'); + + if (!empty($config->recentresponse) and !empty($config->recentfetch)) { + try { + $this->validate_response($config->recentresponse); + $this->recentfetch = $config->recentfetch; + $this->recentresponse = $this->decode_response($config->recentresponse); + } catch (calendarsystem_update_checker_exception $e) { + // The server response is not valid. Behave as if no data were fetched yet. + // This may happen when the most recent update info (cached locally) has been + // fetched with the previous branch of Moodle (like during an upgrade from 2.x + // to 2.y) or when the API of the response has changed. + $this->recentresponse = array(); + } + + } else { + $this->recentresponse = array(); + } + } + + /** + * Returns the URL to send update requests to + * + * @return string URL + */ + protected function prepare_request_url() { + return 'http://foodle.org/calendarsystem/api/updates.php'; + } + + /** + * Sets the properties currentversion, currentrelease, currentbranch and currentplugins + * + * @param bool $forcereload + */ + protected function load_current_environment($forcereload=false) { + global $CFG; + + if (!is_null($this->currentversion) and !$forcereload) { + // nothing to do + return; + } + + $version = null; + $plugin = new stdClass(); + + include($CFG->dirroot.'/calendarsystem/version.php'); + $this->currentversion = $version; + + $calendars = get_plugin_list('calendarsystem'); + + foreach ($calendars as $calendar => $calendarrootdir) { + include($calendarrootdir.'/version.php'); + $this->currentplugins[$calendar] = $plugin->version; + } + } + + /** + * Returns the list of HTTP params to be sent to the updates provider URL + * + * @return array of (string)param => (string)value + */ + protected function prepare_request_params() { + global $CFG; + + $this->load_current_environment(); +// $this->restore_response(); + + $params = array(); + $params['format'] = 'json'; + + if (isset($this->currentversion)) { + $params['version'] = $this->currentversion; + } else { + throw new coding_exception('Main calendarsystem version must be already known here'); + } + + $plugins = array(); + foreach ($this->currentplugins as $plugin => $version) { + $plugins[] = $plugin.'@'.$version; + } + if (!empty($plugins)) { + $params['plugins'] = implode(',', $plugins); + } + + $params['url'] = $CFG->wwwroot; + + return $params; + } + +} + +/** + * Defines the structure of objects returned by {@link calendarsystem_update_checker::get_update_info()} + */ +class calendarsystem_update_info { + + /** @var string frankenstyle component name */ + public $component; + /** @var int the available version of the component */ + public $version; + /** @var string|null optional URL of a page with more info about the update */ + public $url = null; + /** @var string|null optional URL of a ZIP package that can be downloaded and installed */ + public $download = null; + /** @var string|null if self::download is set, then this must be the MD5 hash of the ZIP */ + public $downloadmd5 = null; + + /** + * Creates new instance of the class + * + * The $info array must provide at least the 'version' value and optionally all other + * values to populate the object's properties. + * + * @param string $name the frankenstyle component name + * @param array $info associative array with other properties + */ + public function __construct($name, array $info) { + $this->component = $name; + foreach ($info as $k => $v) { + if (property_exists('calendarsystem_update_info', $k) and $k != 'component') { + $this->$k = $v; + } + } + } +} +?> \ No newline at end of file diff --git a/calendarsystem/version.php b/calendarsystem/version.php new file mode 100644 index 0000000000000..24c4d6d02a418 --- /dev/null +++ b/calendarsystem/version.php @@ -0,0 +1,28 @@ +. + +/** + * Version details + * + * @package calendarsystem + * @author Shamim Rezaie + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) diff --git a/course/edit_form.php b/course/edit_form.php index 06f74359cfc70..983a7e0fb7547 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -271,6 +271,13 @@ function definition() { $mform->addElement('select', 'defaultgroupingid', get_string('defaultgrouping', 'group'), $options); //-------------------------------------------------------------------------------- + // MDL-18375, Multi-Calendar Support + $mform->addElement('header','', get_string('calendar', 'calendar')); + + $calendarsystems = array(); + $calendarsystems[''] = get_string('forceno'); + $calendarsystems += get_list_of_calendars(); + $mform->addElement('select', 'calendarsystem', get_string('forcecalendarsystem', 'calendarsystem'), $calendarsystems); /// customizable role names in this course //-------------------------------------------------------------------------------- diff --git a/enrol/manual/ajax.php b/enrol/manual/ajax.php index c1a6f80c9b374..6fcdb8dd1f8a8 100644 --- a/enrol/manual/ajax.php +++ b/enrol/manual/ajax.php @@ -113,8 +113,10 @@ break; case 3: default: + // MDL-18375, Multi-Calendar Support + $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); - $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); + $today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); $timestart = $today; break; } diff --git a/enrol/manual/lib.php b/enrol/manual/lib.php index 10e12e1e4b011..03b2a9883c18b 100644 --- a/enrol/manual/lib.php +++ b/enrol/manual/lib.php @@ -230,8 +230,10 @@ public function get_manual_enrol_button(course_enrolment_manager $manager) { if ($startdate > 0) { $startdateoptions[2] = get_string('coursestart') . ' (' . userdate($startdate, $timeformat) . ')'; } + // MDL-18375, Multi-Calendar Support + $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); - $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); + $today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); $startdateoptions[3] = get_string('today') . ' (' . userdate($today, $timeformat) . ')' ; $defaultduration = $instance->enrolperiod > 0 ? $instance->enrolperiod / 86400 : ''; diff --git a/enrol/manual/manage.php b/enrol/manual/manage.php index 7d91e4b6017ba..96ac9de6650bc 100644 --- a/enrol/manual/manage.php +++ b/enrol/manual/manage.php @@ -92,8 +92,11 @@ // Build the list of options for the starting from dropdown. $timeformat = get_string('strftimedatefullshort'); + +// MDL-18375, Multi-Calendar Support +$calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); -$today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); +$today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); // Enrolment start. $basemenu = array(); diff --git a/lang/en/calendarsystem.php b/lang/en/calendarsystem.php new file mode 100644 index 0000000000000..51b607c0a84d6 --- /dev/null +++ b/lang/en/calendarsystem.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/lang/en/plugin.php b/lang/en/plugin.php index e65e1ea7f186e..630dbf64789a6 100644 --- a/lang/en/plugin.php +++ b/lang/en/plugin.php @@ -91,6 +91,7 @@ $string['type_cachelock_plural'] = 'Cache lock handlers'; $string['type_cachestore'] = 'Cache store'; $string['type_cachestore_plural'] = 'Cache stores'; +$string['type_calendarsystem_plural'] = 'Calendar systems'; $string['type_coursereport'] = 'Course report'; $string['type_coursereport_plural'] = 'Course reports'; $string['type_editor'] = 'Editor'; diff --git a/lib/bennu/iCalendar_rfc2445.php b/lib/bennu/iCalendar_rfc2445.php index d221217c61013..ffe4f85daff4b 100644 --- a/lib/bennu/iCalendar_rfc2445.php +++ b/lib/bennu/iCalendar_rfc2445.php @@ -203,7 +203,9 @@ function rfc2445_is_valid_value($value, $type) { $m = intval(substr($value, 4, 2)); $d = intval(substr($value, 6, 2)); - return checkdate($m, $d, $y); + // MDL-18375, Multi-Calendar Support + $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); + return $calendarsystem_gregorian->checkdate($m, $d, $y); break; case RFC2445_TYPE_DATE_TIME: diff --git a/lib/db/install.xml b/lib/db/install.xml index cb6b59793e6a6..ac6eb778b6449 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -93,6 +93,7 @@ + @@ -771,6 +772,7 @@ + diff --git a/lib/form/dateselector.php b/lib/form/dateselector.php index f4cb2c5bcfd13..d578e84572ea1 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -43,6 +43,9 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { /** * Control the fieldnames for form elements + * + * MDL-18375, Multi-Calendar Support + * * startyear => int start of range of years that can be selected * stopyear => int last year that can be selected * timezone => int|float|string (optional) timezone modifier used for edge case only. @@ -52,8 +55,8 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group * optional => if true, show a checkbox beside the date to turn it on (or off) * @var array */ - protected $_options = array('startyear' => 1970, 'stopyear' => 2020, - 'timezone' => 99, 'optional' => false); + protected $_options = array('startyear' => null, 'stopyear' => null, + 'timezone' => null, 'optional' => null); /** * @var array These complement separators, they are appended to the resultant HTML. @@ -77,6 +80,12 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group */ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; + + $this->_options = array('startyear'=> $CALENDARSYSTEM->get_min_year(), 'stopyear'=>$CALENDARSYSTEM->get_max_year(), + 'timezone'=>99, 'optional'=>false); + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); $this->_persistantFreeze = true; $this->_appendName = true; @@ -93,7 +102,8 @@ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null } } } - form_init_date_js(); + // MDL-18375, Multi-Calendar Support + // form_init_date_js(); } /** @@ -103,15 +113,13 @@ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null */ function _createElements() { - global $OUTPUT; + global $OUTPUT, $CALENDARSYSTEM; $this->_elements = array(); for ($i=1; $i<=31; $i++) { $days[$i] = $i; } - for ($i=1; $i<=12; $i++) { - $months[$i] = userdate(gmmktime(12,0,0,$i,15,2000), "%B"); - } + $months = $CALENDARSYSTEM->get_month_names(); for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) { $years[$i] = $i; } diff --git a/lib/form/datetimeselector.php b/lib/form/datetimeselector.php index 0bc6a7730c56a..cf4f884a49e06 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -42,6 +42,9 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ /** * Options for the element + * + * MDL-18375, Multi-Calendar Support + * * startyear => int start of range of years that can be selected * stopyear => int last year that can be selected * defaulttime => default time value if the field is currently not set @@ -53,8 +56,8 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ * optional => if true, show a checkbox beside the date to turn it on (or off) * @var array */ - var $_options = array('startyear' => 1970, 'stopyear' => 2020, 'defaulttime' => 0, - 'timezone' => 99, 'step' => 5, 'optional' => false); + var $_options = array('startyear' => null, 'stopyear' => null, 'defaulttime' => null, + 'timezone' => null, 'step' => null, 'optional' => null); /** * @var array These complement separators, they are appended to the resultant HTML. @@ -78,6 +81,12 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ */ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; + + $this->_options = array('startyear'=> $CALENDARSYSTEM->get_min_year(), 'stopyear'=>$CALENDARSYSTEM->get_max_year(), + 'defaulttime' => 0, 'timezone'=>99, 'step'=>5, 'optional'=>false); + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); $this->_persistantFreeze = true; $this->_appendName = true; @@ -94,7 +103,8 @@ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = } } } - form_init_date_js(); + // MDL-18375, Multi-Calendar Support + // form_init_date_js(); } /** @@ -104,15 +114,13 @@ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = */ function _createElements() { - global $OUTPUT; + global $OUTPUT, $CALENDARSYSTEM; $this->_elements = array(); for ($i=1; $i<=31; $i++) { $days[$i] = $i; } - for ($i=1; $i<=12; $i++) { - $months[$i] = userdate(gmmktime(12,0,0,$i,15,2000), "%B"); - } + $months = $CALENDARSYSTEM->get_month_names(); for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) { $years[$i] = $i; } diff --git a/lib/moodlelib.php b/lib/moodlelib.php index a0fae10295d4e..e01f2b64780a5 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -2003,6 +2003,8 @@ function get_user_preferences($name = null, $default = null, $user = null) { /** * Given date parts in user time produce a GMT timestamp. * + * MDL-18375, Multi-Calendar Support + * * @package core * @category time * @param int $year The year part to create timestamp of @@ -2018,6 +2020,16 @@ function get_user_preferences($name = null, $default = null, $user = null) { * @return int GMT timestamp */ function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { + global $CALENDARSYSTEM; + if ($CALENDARSYSTEM->get_min_year() == 1350 && $year > 2000) { + debugging('Warning. Wrong call to make_timestamp().', DEBUG_DEVELOPER); + error('Your code must be fixed by a developer.'); + } + return $CALENDARSYSTEM->make_timestamp($year, $month, $day, $hour, $minute, $second, $timezone, $applydst); +} + +// MDL-18375, Multi-Calendar Support +function make_timestamp_old($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { // Save input timezone, required for dst offset check. $passedtimezone = $timezone; @@ -2144,6 +2156,8 @@ function format_time($totalsecs, $str = null) { * If parameter fixday = true (default), then take off leading * zero from %d, else maintain it. * + * MDL-18375, Multi-Calendar Support + * * @package core * @category time * @param int $date the timestamp in UTC, as obtained from the database. @@ -2158,6 +2172,12 @@ function format_time($totalsecs, $str = null) { * @return string the formatted date/time. */ function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) { + global $CALENDARSYSTEM; + return $CALENDARSYSTEM->userdate($date, $format, $timezone, $fixday, $fixhour); +} + +// MDL-18375, Multi-Calendar Support +function userdate_old($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) { global $CFG; @@ -2267,6 +2287,8 @@ function date_format_string($date, $format, $tz = 99) { * Given a $time timestamp in GMT (seconds since epoch), * returns an array that represents the date in user time * + * MDL-18375, Multi-Calendar Support + * * @package core * @category time * @uses HOURSECS @@ -2275,7 +2297,13 @@ function date_format_string($date, $format, $tz = 99) { * dst offset is applied {@link http://docs.moodle.org/dev/Time_API#Timezone} * @return array An array that represents the date in user time */ -function usergetdate($time, $timezone=99) { + function usergetdate($time, $timezone=99) { + global $CALENDARSYSTEM; + return $CALENDARSYSTEM->usergetdate($time, $timezone); +} + +// MDL-18375, Multi-Calendar Support +function usergetdate_old($time, $timezone=99) { // Save input timezone, required for dst offset check. $passedtimezone = $timezone; @@ -2644,6 +2672,8 @@ function calculate_user_dst_table($fromyear = null, $toyear = null, $strtimezone /** * Calculates the required DST change and returns a Timestamp Array * + * MDL-18375, Multi-Calendar Support + * * @package core * @category time * @uses HOURSECS @@ -2665,8 +2695,10 @@ function dst_changes_for_year($year, $timezone) { list($dsthour, $dstmin) = explode(':', $timezone->dst_time); list($stdhour, $stdmin) = explode(':', $timezone->std_time); - $timedst = make_timestamp($year, $timezone->dst_month, $monthdaydst, 0, 0, 0, 99, false); - $timestd = make_timestamp($year, $timezone->std_month, $monthdaystd, 0, 0, 0, 99, false); + // MDL-18375, Multi-Calendar Support + $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); + $timedst = $calendarsystem_gregorian->make_timestamp($year, $timezone->dst_month, $monthdaydst, 0, 0, 0, 99, false); + $timestd = $calendarsystem_gregorian->make_timestamp($year, $timezone->std_month, $monthdaystd, 0, 0, 0, 99, false); // Instead of putting hour and minute in make_timestamp(), we add them afterwards. // This has the advantage of being able to have negative values for hour, i.e. for timezones @@ -2742,6 +2774,9 @@ function dst_offset_on($time, $strtimezone = null) { */ function find_day_in_month($startday, $weekday, $month, $year) { + // MDL-18375, Multi-Calendar Support + $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); + $daysinmonth = days_in_month($month, $year); if ($weekday == -1) { @@ -2763,7 +2798,7 @@ function find_day_in_month($startday, $weekday, $month, $year) { if ($startday < 1) { $startday = abs($startday); - $lastmonthweekday = strftime('%w', mktime(12, 0, 0, $month, $daysinmonth, $year)); + $lastmonthweekday = strftime('%w', $calendarsystem_gregorian->mktime(12, 0, 0, $month, $daysinmonth, $year)); // This is the last such weekday of the month. $lastinmonth = $daysinmonth + $weekday - $lastmonthweekday; @@ -2780,7 +2815,7 @@ function find_day_in_month($startday, $weekday, $month, $year) { } else { - $indexweekday = strftime('%w', mktime(12, 0, 0, $month, $startday, $year)); + $indexweekday = strftime('%w', $calendarsystem_gregorian->mktime(12, 0, 0, $month, $startday, $year)); $diff = $weekday - $indexweekday; if ($diff < 0) { @@ -2811,6 +2846,8 @@ function days_in_month($month, $year) { /** * Calculate the position in the week of a specific calendar day * + * MDL-18375, Multi-Calendar Support + * * @package core * @category time * @param int $day The day of the date whose position in the week is sought @@ -2819,8 +2856,9 @@ function days_in_month($month, $year) { * @return int */ function dayofweek($day, $month, $year) { - // I wonder if this is any different from strftime('%w', mktime(12, 0, 0, $month, $daysinmonth, $year, 0));. - return intval(date('w', mktime(12, 0, 0, $month, $day, $year))); + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; + return $CALENDARSYSTEM->dayofweek($day, $month, $year); } // USER AUTHENTICATION AND LOGIN. diff --git a/lib/setup.php b/lib/setup.php index ecf4917655947..27fb471b5ad60 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -482,6 +482,13 @@ */ global $SCRIPT; +/** + * MDL-18375, Multi-Calendar Support + * + * $CALENDARSYSTEM is a global that defines the calendar system + */ +global $CALENDARSYSTEM; + // Set httpswwwroot default value (this variable will replace $CFG->wwwroot // inside some URLs used in HTTPSPAGEREQUIRED pages. $CFG->httpswwwroot = $CFG->wwwroot; @@ -561,6 +568,7 @@ require_once($CFG->libdir .'/messagelib.php'); // Messagelib functions require_once($CFG->libdir .'/modinfolib.php'); // Cached information on course-module instances require_once($CFG->dirroot.'/cache/lib.php'); // Cache API +require_once($CFG->dirroot . '/calendarsystem/calendarsystem.class.php'); // MDL-18375, Multi-Calendar Support // make sure PHP is not severly misconfigured setup_validate_php_configuration(); @@ -971,6 +979,26 @@ function stripslashes_deep($value) { } } +// MDL-18375, Multi-Calendar Support +// note: do not accept calendarsystem parameter from POST +if (isset($_GET['calendarsystem']) and ($calendarsystem = optional_param('calendarsystem', '', PARAM_SAFEDIR))) { + if (file_exists($CFG->dirroot .'/calendarsystem/'. $calendarsystem)) { + $SESSION->calendarsystem = $calendarsystem; + } +} + +unset($calendarsystem); + +if (empty($CFG->calendarsystem)) { + if (empty($SESSION->calendarsystem)) { + $CFG->calendarsystem = 'gregorian'; + } else { + $CFG->calendarsystem = $SESSION->calendarsystem; + } +} + +$CALENDARSYSTEM = calendarsystem_plugin_factory::factory(); + // note: we can not block non utf-8 installations here, because empty mysql database // might be converted to utf-8 in admin/index.php during installation diff --git a/user/editlib.php b/user/editlib.php index 42489b19a0412..9b40e635389a1 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -262,6 +262,10 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager $mform->addElement('select', 'lang', get_string('preferredlanguage'), get_string_manager()->get_list_of_translations()); $mform->setDefault('lang', $CFG->lang); + // MDL-18375, Multi-Calendar Support + $mform->addElement('select', 'calendarsystem', get_string('preferredcalendar', 'calendarsystem'), get_list_of_calendars()); + $mform->setDefault('calendarsystem', $CFG->calendarsystem); + if (!empty($CFG->allowuserthemes)) { $choices = array(); $choices[''] = get_string('default'); diff --git a/user/profile/field/datetime/define.class.php b/user/profile/field/datetime/define.class.php index 5e454925b60d4..53a9ad65f6ee6 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -16,8 +16,12 @@ class profile_define_datetime extends profile_define_base { * @param object $form the user form */ function define_form_specific($form) { + // MDL-18375, Multi-Calendar Support + global $CALENDARSYSTEM; + // Create variables to store start and end - $currentyear = date('Y'); + $userdate = $CALENDARSYSTEM->usergetdate(time()); + $currentyear = $userdate['year']; $startyear = $currentyear - 100; $endyear = $currentyear + 20; From 2f00e1b245ecc0d4d83c8d5774df3cb6b12ccde5 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Mon, 10 Jun 2013 17:35:55 +0800 Subject: [PATCH 02/16] MDL-18375 calendar: huge refactor of the initial patch 1) Moved the calendar types location to a sub-folder in the calendar directory. 2) Removed/moved language strings. 3) Removed calendar types that should be downloaded as plugins. 4) Removed a Non-English language pack for the Gregorian calendar type that should be downloaded separately. 5) Removed custom files responsible for checking for updates and uninstalling calendar types, which should be done by core. 6) Removed JS from the calendar_month block as there is no non-JS alternative provided and the JS written does not make use of the YUI library to ensure multiple browser support. 7) Removed code from the base class responsible for creating timestamps that are saved in the DB. 8) Added PHPDocs. Note: In the original patch we are editing core functions responsible for saving time in the database in the calendar base class. This is very dangerous, we do not want to touch these functions as it could cause a complete fubar of the database. There are places we are forcing the use of the gregorian calendar as we are passing dates generated by the PHP date function, where as sometimes we pass dates from usergetdate (which was being overwritten to return the date specific to the calendar). We can not expect third party modules to change the calendar type depending on the format they pass to these functions. --- admin/settings/appearance.php | 2 - admin/settings/plugins.php | 7 - admin/tool/uploaduser/index.php | 4 +- .../calendar_month/block_calendar_month.php | 41 +-- calendar/event.php | 5 +- calendar/export_execute.php | 28 +- calendar/lib.php | 31 +- calendar/renderer.php | 10 +- calendar/type/calendartype.class.php | 304 ++++++++++++++++ .../lang/en/calendartype_gregorian.php | 15 +- calendar/type/gregorian/lib.php | 133 +++++++ .../type/gregorian}/version.php | 16 +- calendar/view.php | 3 +- calendarsystem/admin.php | 98 ----- calendarsystem/calendarsystem.class.php | 69 ---- calendarsystem/gregorian/calendarsystem.php | 88 ----- .../lang/en/calendarsystem_gregorian.php | 8 - .../lang/fa/calendarsystem_gregorian.php | 8 - calendarsystem/gregorian/version.php | 31 -- calendarsystem/hijri/calendarsystem.php | 250 ------------- .../hijri/lang/en/calendarsystem_hijri.php | 27 -- .../hijri/lang/fa/calendarsystem_hijri.php | 27 -- calendarsystem/index.php | 175 --------- calendarsystem/jalali/calendarsystem.php | 289 --------------- .../jalali/lang/en/calendarsystem_jalali.php | 27 -- .../jalali/lang/fa/calendarsystem_jalali.php | 27 -- calendarsystem/jalali/version.php | 31 -- calendarsystem/updatechecker.php | 341 ------------------ course/edit_form.php | 44 ++- enrol/manual/ajax.php | 4 +- enrol/manual/lib.php | 4 +- enrol/manual/manage.php | 5 +- lang/en/admin.php | 3 +- lang/en/calendar.php | 2 + lang/en/calendarsystem.php | 19 - lang/en/plugin.php | 3 +- lib/bennu/iCalendar_rfc2445.php | 4 +- lib/classes/component.php | 1 + lib/db/install.xml | 4 +- lib/form/dateselector.php | 68 ++-- lib/form/datetimeselector.php | 75 ++-- lib/moodlelib.php | 166 +-------- lib/setup.php | 29 +- user/editlib.php | 5 +- user/profile/field/datetime/define.class.php | 6 +- 45 files changed, 606 insertions(+), 1931 deletions(-) create mode 100644 calendar/type/calendartype.class.php rename calendarsystem/version.php => calendar/type/gregorian/lang/en/calendartype_gregorian.php (67%) create mode 100644 calendar/type/gregorian/lib.php rename {calendarsystem/hijri => calendar/type/gregorian}/version.php (59%) delete mode 100644 calendarsystem/admin.php delete mode 100644 calendarsystem/calendarsystem.class.php delete mode 100644 calendarsystem/gregorian/calendarsystem.php delete mode 100644 calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php delete mode 100644 calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php delete mode 100644 calendarsystem/gregorian/version.php delete mode 100644 calendarsystem/hijri/calendarsystem.php delete mode 100644 calendarsystem/hijri/lang/en/calendarsystem_hijri.php delete mode 100644 calendarsystem/hijri/lang/fa/calendarsystem_hijri.php delete mode 100644 calendarsystem/index.php delete mode 100644 calendarsystem/jalali/calendarsystem.php delete mode 100644 calendarsystem/jalali/lang/en/calendarsystem_jalali.php delete mode 100644 calendarsystem/jalali/lang/fa/calendarsystem_jalali.php delete mode 100644 calendarsystem/jalali/version.php delete mode 100644 calendarsystem/updatechecker.php delete mode 100644 lang/en/calendarsystem.php diff --git a/admin/settings/appearance.php b/admin/settings/appearance.php index b5293df9ab551..1ee3a7ad2c41a 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -45,8 +45,6 @@ array('0' => new lang_string('default', 'calendar'), '%I:%M %p' => new lang_string('timeformat_12', 'calendar'), '%H:%M' => new lang_string('timeformat_24', 'calendar')))); - // MDL-18375, Multi-Calendar Support - $temp->add(new admin_setting_configselect('calendarsystem', new lang_string('configcalendarsystem', 'calendarsystem'), new lang_string('helpcalendarsystem', 'calendarsystem'), 'gregorian', get_list_of_calendars())); $temp->add(new admin_setting_configselect('calendar_startwday', new lang_string('configstartwday', 'admin'), new lang_string('helpstartofweek', 'admin'), 0, array( 0 => new lang_string('sunday', 'calendar'), diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index 4587d3412ee67..502d5e667ad37 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -454,13 +454,6 @@ } } -// calendarsystem plugins -if ($hassiteconfig) { - $ADMIN->add('modules', new admin_category('calendarsystems', new lang_string('calendarsystems', 'calendarsystem'))); - $ADMIN->add('calendarsystems', new admin_externalpage('managecalendarsystems', new lang_string('calendarsystemsmanage', 'calendarsystem'), $CFG->wwwroot .'/calendarsystem/admin.php')); - $ADMIN->add('calendarsystems', new admin_externalpage('updatecalendarsystems', new lang_string('checkforupdates', 'calendarsystem'), $CFG->wwwroot .'/calendarsystem/index.php')); -} - /// Add all local plugins - must be always last! if ($hassiteconfig) { $ADMIN->add('modules', new admin_category('localplugins', new lang_string('localplugins'))); diff --git a/admin/tool/uploaduser/index.php b/admin/tool/uploaduser/index.php index d2144139cca09..7949d94eada6b 100644 --- a/admin/tool/uploaduser/index.php +++ b/admin/tool/uploaduser/index.php @@ -81,10 +81,8 @@ $returnurl = new moodle_url('/admin/tool/uploaduser/index.php'); $bulknurl = new moodle_url('/admin/user/user_bulk.php'); -// MDL-18375, Multi-Calendar Support -$calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); -$today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); +$today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); // array of all valid fields for validation $STD_FIELDS = array('id', 'firstname', 'lastname', 'username', 'email', diff --git a/blocks/calendar_month/block_calendar_month.php b/blocks/calendar_month/block_calendar_month.php index 11e816264a951..abe28089e9e47 100644 --- a/blocks/calendar_month/block_calendar_month.php +++ b/blocks/calendar_month/block_calendar_month.php @@ -10,7 +10,7 @@ function preferred_width() { } function get_content() { - global $USER, $CFG, $SESSION, $COURSE, $OUTPUT; + global $USER, $CFG, $SESSION; $cal_m = optional_param( 'cal_m', 0, PARAM_INT ); $cal_y = optional_param( 'cal_y', 0, PARAM_INT ); @@ -51,45 +51,6 @@ function get_content() { $this->content->text .= '
'.calendar_filter_controls($this->page->url).'
'; } - // MDL-18375, Multi-Calendar Support - if (empty($COURSE->calendarsystem)) { - // the course has not a forced calendarsystem - // so user can change it. - $url = $CFG->wwwroot . (!empty($COURSE->id) && ($COURSE->id!= SITEID) ? "/course/view.php?id={$COURSE->id}" : '/index.php'); - $url = new moodle_url($url); - - $calendarselect = new single_select($url, 'calendarsystem', get_list_of_calendars(), current_calendarsystem_plugin(), false, 'choosecalendar'); - $calendarselect->set_label(''.get_string('system', 'calendarsystem').''); - - $this->content->text .= ' - - ' . $OUTPUT->render($calendarselect) . ' - - '; - } - return $this->content; } } diff --git a/calendar/event.php b/calendar/event.php index 71717a8e15151..027527bf9dc05 100644 --- a/calendar/event.php +++ b/calendar/event.php @@ -133,10 +133,9 @@ unset($formoptions->eventtypes->groups); } } - // MDL-18375, Multi-Calendar Support - if($cal_y && $cal_m && $cal_d && $CALENDARSYSTEM->checkdate($cal_m, $cal_d, $cal_y)) { + if($cal_y && $cal_m && $cal_d && checkdate($cal_m, $cal_d, $cal_y)) { $event->timestart = make_timestamp($cal_y, $cal_m, $cal_d, 0, 0, 0); - } else if($cal_y && $cal_m && $CALENDARSYSTEM->checkdate($cal_m, 1, $cal_y)) { + } else if($cal_y && $cal_m && checkdate($cal_m, 1, $cal_y)) { $now = usergetdate(time()); if($cal_y == $now['year'] && $cal_m == $now['mon']) { $event->timestart = make_timestamp($cal_y, $cal_m, $now['mday'], 0, 0, 0); diff --git a/calendar/export_execute.php b/calendar/export_execute.php index f5e638a65f67f..7cd585bdcf0c5 100644 --- a/calendar/export_execute.php +++ b/calendar/export_execute.php @@ -34,9 +34,7 @@ $what = optional_param('preset_what', 'all', PARAM_ALPHA); $time = optional_param('preset_time', 'weeknow', PARAM_ALPHA); -// MDL-18375, Multi-Calendar Support -$calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); -$now = $calendarsystem_gregorian->usergetdate(time()); +$now = usergetdate(time()); // Let's see if we have sufficient and correct data $allowed_what = array('all', 'courses'); $allowed_time = array('weeknow', 'weeknext', 'monthnow', 'monthnext', 'recentupcoming', 'custom'); @@ -82,47 +80,47 @@ $startmonthday = find_day_in_month($now['mday'] - 6, $startweekday, $now['mon'], $now['year']); $startmonth = $now['mon']; $startyear = $now['year']; - if($startmonthday > $calendarsystem_gregorian->calendar_days_in_month($startmonth, $startyear)) { + if($startmonthday > calendar_days_in_month($startmonth, $startyear)) { list($startmonth, $startyear) = calendar_add_month($startmonth, $startyear); $startmonthday = find_day_in_month(1, $startweekday, $startmonth, $startyear); } - $timestart = $calendarsystem_gregorian->make_timestamp($startyear, $startmonth, $startmonthday); + $timestart = make_timestamp($startyear, $startmonth, $startmonthday); $endmonthday = $startmonthday + 7; $endmonth = $startmonth; $endyear = $startyear; - if($endmonthday > $calendarsystem_gregorian->calendar_days_in_month($endmonth, $endyear)) { + if($endmonthday > calendar_days_in_month($endmonth, $endyear)) { list($endmonth, $endyear) = calendar_add_month($endmonth, $endyear); $endmonthday = find_day_in_month(1, $startweekday, $endmonth, $endyear); } - $timeend = $calendarsystem_gregorian->make_timestamp($endyear, $endmonth, $endmonthday) - 1; + $timeend = make_timestamp($endyear, $endmonth, $endmonthday) - 1; break; case 'weeknext': $startweekday = get_user_preferences('calendar_startwday', calendar_get_starting_weekday()); $startmonthday = find_day_in_month($now['mday'] + 1, $startweekday, $now['mon'], $now['year']); $startmonth = $now['mon']; $startyear = $now['year']; - if($startmonthday > $calendarsystem_gregorian->calendar_days_in_month($startmonth, $startyear)) { + if($startmonthday > calendar_days_in_month($startmonth, $startyear)) { list($startmonth, $startyear) = calendar_add_month($startmonth, $startyear); $startmonthday = find_day_in_month(1, $startweekday, $startmonth, $startyear); } - $timestart = $calendarsystem_gregorian->make_timestamp($startyear, $startmonth, $startmonthday); + $timestart = make_timestamp($startyear, $startmonth, $startmonthday); $endmonthday = $startmonthday + 7; $endmonth = $startmonth; $endyear = $startyear; - if($endmonthday > $calendarsystem_gregorian->calendar_days_in_month($endmonth, $endyear)) { + if($endmonthday > calendar_days_in_month($endmonth, $endyear)) { list($endmonth, $endyear) = calendar_add_month($endmonth, $endyear); $endmonthday = find_day_in_month(1, $startweekday, $endmonth, $endyear); } - $timeend = $calendarsystem_gregorian->make_timestamp($endyear, $endmonth, $endmonthday) - 1; + $timeend = make_timestamp($endyear, $endmonth, $endmonthday) - 1; break; case 'monthnow': - $timestart = $calendarsystem_gregorian->make_timestamp($now['year'], $now['mon'], 1); - $timeend = $calendarsystem_gregorian->make_timestamp($now['year'], $now['mon'], calendar_days_in_month($now['mon'], $now['year']), 23, 59, 59); + $timestart = make_timestamp($now['year'], $now['mon'], 1); + $timeend = make_timestamp($now['year'], $now['mon'], calendar_days_in_month($now['mon'], $now['year']), 23, 59, 59); break; case 'monthnext': list($nextmonth, $nextyear) = calendar_add_month($now['mon'], $now['year']); - $timestart = $calendarsystem_gregorian->make_timestamp($nextyear, $nextmonth, 1); - $timeend = $calendarsystem_gregorian->make_timestamp($nextyear, $nextmonth, calendar_days_in_month($nextmonth, $nextyear), 23, 59, 59); + $timestart = make_timestamp($nextyear, $nextmonth, 1); + $timeend = make_timestamp($nextyear, $nextmonth, calendar_days_in_month($nextmonth, $nextyear), 23, 59, 59); break; case 'recentupcoming': //Events in the last 5 or next 60 days diff --git a/calendar/lib.php b/calendar/lib.php index 20f5a8f28e1d5..ede82803316b5 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -187,8 +187,6 @@ function calendar_get_starting_weekday() { */ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_year = false, $placement = false, $courseid = false ) { global $CFG, $USER, $OUTPUT; - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; $display = new stdClass; $display->minwday = get_user_preferences('calendar_startwday', calendar_get_starting_weekday()); @@ -204,7 +202,7 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y $display->thismonth = true; } else { // Navigated to other month, let's do a nice trick and save us a lot of work... - if(!$CALENDARSYSTEM->checkdate($cal_month, 1, $cal_year)) { + if(!checkdate($cal_month, 1, $cal_year)) { $date = array('mday' => 1, 'mon' => $thisdate['mon'], 'year' => $thisdate['year']); $display->thismonth = true; } else { @@ -223,12 +221,12 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y if (get_user_timezone_offset() < 99) { // We 'll keep these values as GMT here, and offset them when the time comes to query the db - $display->tstart = $CALENDARSYSTEM->gmmktime(0, 0, 0, $m, 1, $y); // This is GMT - $display->tend = $CALENDARSYSTEM->gmmktime(23, 59, 59, $m, $display->maxdays, $y); // GMT + $display->tstart = gmmktime(0, 0, 0, $m, 1, $y); // This is GMT + $display->tend = gmmktime(23, 59, 59, $m, $display->maxdays, $y); // GMT } else { // no timezone info specified - $display->tstart = $CALENDARSYSTEM->mktime(0, 0, 0, $m, 1, $y); - $display->tend = $CALENDARSYSTEM->mktime(23, 59, 59, $m, $display->maxdays, $y); + $display->tstart = mktime(0, 0, 0, $m, 1, $y); + $display->tend = mktime(23, 59, 59, $m, $display->maxdays, $y); } $startwday = dayofweek(1, $m, $y); @@ -826,8 +824,6 @@ function calendar_get_events_by_id($eventids) { */ function calendar_top_controls($type, $data) { global $CFG, $PAGE; - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; $content = ''; if(!isset($data['d'])) { $data['d'] = 1; @@ -840,11 +836,11 @@ function calendar_top_controls($type, $data) { $courseid = '&course='.$data['id']; } - if(!$CALENDARSYSTEM->checkdate($data['m'], $data['d'], $data['y'])) { + if(!checkdate($data['m'], $data['d'], $data['y'])) { $time = time(); } else { - $time = $CALENDARSYSTEM->make_timestamp($data['y'], $data['m'], $data['d']); + $time = make_timestamp($data['y'], $data['m'], $data['d']); } $date = usergetdate($time); @@ -1214,9 +1210,7 @@ function calendar_wday_name($englishname) { * @return int */ function calendar_days_in_month($month, $year) { - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; - return $CALENDARSYSTEM->calendar_days_in_month($month, $year); + return intval(date('t', mktime(0, 0, 0, $month, 1, $year))); } /** @@ -1739,11 +1733,10 @@ function calendar_format_event_time($event, $now, $linkparams = null, $usecommon * @param string|array $selected options for select elements */ function calendar_print_month_selector($name, $selected) { - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; - - $months = $CALENDARSYSTEM->get_month_names(); - + $months = array(); + for ($i=1; $i<=12; $i++) { + $months[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), '%B'); + } echo html_writer::label(get_string('months'), 'menu'. $name, false, array('class' => 'accesshide')); echo html_writer::select($months, $name, $selected, false); } diff --git a/calendar/renderer.php b/calendar/renderer.php index 1e05d89b463fe..4fc9a05d76c33 100644 --- a/calendar/renderer.php +++ b/calendar/renderer.php @@ -380,8 +380,6 @@ public function event(calendar_event $event, $showactions=true) { */ public function show_month_detailed(calendar_information $calendar, moodle_url $returnurl = null) { global $CFG; - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; if (empty($returnurl)) { $returnurl = $this->page->url; @@ -398,13 +396,13 @@ public function show_month_detailed(calendar_information $calendar, moodle_url $ $startwday = 0; if (get_user_timezone_offset() < 99) { // We 'll keep these values as GMT here, and offset them when the time comes to query the db - $display->tstart = $CALENDARSYSTEM->gmmktime(0, 0, 0, $calendar->month, 1, $calendar->year); // This is GMT - $display->tend = $CALENDARSYSTEM->gmmktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); // GMT + $display->tstart = gmmktime(0, 0, 0, $calendar->month, 1, $calendar->year); // This is GMT + $display->tend = gmmktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); // GMT $startwday = gmdate('w', $display->tstart); // $display->tstart is already GMT, so don't use date(): messes with server's TZ } else { // no timezone info specified - $display->tstart = $CALENDARSYSTEM->mktime(0, 0, 0, $calendar->month, 1, $calendar->year); - $display->tend = $CALENDARSYSTEM->mktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); + $display->tstart = mktime(0, 0, 0, $calendar->month, 1, $calendar->year); + $display->tend = mktime(23, 59, 59, $calendar->month, $display->maxdays, $calendar->year); $startwday = date('w', $display->tstart); // $display->tstart not necessarily GMT, so use date() } diff --git a/calendar/type/calendartype.class.php b/calendar/type/calendartype.class.php new file mode 100644 index 0000000000000..becdd6428738d --- /dev/null +++ b/calendar/type/calendartype.class.php @@ -0,0 +1,304 @@ +. + +/** + * Defines functions used by calendar type plugins. + * + * This library provides a unified interface for calendar types. + * + * @package core_calendar + * @author Shamim Rezaie + * @author Mark Nelson + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class calendar_type_plugin_base { + + /** + * Returns a list of all the possible days for all months. + * + * This is used to generate the select box for the days + * in the date selector elements. Some months contain more days + * than others so this function should return all possible days as + * we can not predict what month will be chosen (the user + * may have JS turned off and we need to support this situation in + * Moodle). + * + * @return array the days + */ + public abstract function get_days(); + + /** + * Returns a list of all the names of the months. + * + * @return array the month names + */ + public abstract function get_months(); + + /** + * Returns the minimum year of the calendar. + * + * @return int the minumum year + */ + public abstract function get_min_year(); + + /** + * Returns the maximum year of the calendar. + * + * @return int the max year + */ + public abstract function get_max_year(); + + /** + * Provided with a day, month, year, hour and minute in the specific + * calendar type convert it into the equivalent Gregorian date. + * + * @param int $year + * @param int $month + * @param int $day + * @param int $hour + * @param int $minute + * @return array the converted day, month and year. + */ + public abstract function convert_to_gregorian($year, $month, $day, $hour = 0, $minute = 0); + + /** + * Provided with a day, month, year, hour and minute in a Gregorian date + * convert it into the specific calendar type date. + * + * @param int $year + * @param int $month + * @param int $day + * @param int $hour + * @param int $minute + * @return array the converted day, month and year. + */ + public abstract function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0); + + /** + * Returns a formatted string that represents a date in user time. + * + * Returns a formatted string that represents a date in user time + * WARNING: note that the format is for strftime(), not date(). + * Because of a bug in most Windows time libraries, we can't use + * the nicer %e, so we have to use %d which has leading zeroes. + * A lot of the fuss in the function is just getting rid of these leading + * zeroes as efficiently as possible. + * + * If parameter fixday = true (default), then take off leading + * zero from %d, else maintain it. + * + * @param int $date the timestamp in UTC, as obtained from the database. + * @param string $format strftime format. You should probably get this using + * get_string('strftime...', 'langconfig'); + * @param int|float|string $timezone by default, uses the user's time zone. if numeric and + * not 99 then daylight saving will not be added. + * {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @param bool $fixday if true (default) then the leading zero from %d is removed. + * If false then the leading zero is maintained. + * @param bool $fixhour if true (default) then the leading zero from %I is removed. + * @return string the formatted date/time. + */ + function userdate($date, $format, $timezone, $fixday, $fixhour) { + global $CFG; + + if (empty($format)) { + $format = get_string('strftimedaydatetime', 'langconfig'); + } + + if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed. + $fixday = false; + } else if ($fixday) { + $formatnoday = str_replace('%d', 'DD', $format); + $fixday = ($formatnoday != $format); + $format = $formatnoday; + } + + // Note: This logic about fixing 12-hour time to remove unnecessary leading + // zero is required because on Windows, PHP strftime function does not + // support the correct 'hour without leading zero' parameter (%l). + if (!empty($CFG->nofixhour)) { + // Config.php can force %I not to be fixed. + $fixhour = false; + } else if ($fixhour) { + $formatnohour = str_replace('%I', 'HH', $format); + $fixhour = ($formatnohour != $format); + $format = $formatnohour; + } + + // Add daylight saving offset for string timezones only, as we can't get dst for + // float values. if timezone is 99 (user default timezone), then try update dst. + if ((99 == $timezone) || !is_numeric($timezone)) { + $date += dst_offset_on($date, $timezone); + } + + $timezone = get_user_timezone_offset($timezone); + + // If we are running under Windows convert to windows encoding and then back to UTF-8 + // (because it's impossible to specify UTF-8 to fetch locale info in Win32). + if (abs($timezone) > 13) { // Server time. + $datestring = date_format_string($date, $format, $timezone); + if ($fixday) { + $daystring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %d', $date))); + $datestring = str_replace('DD', $daystring, $datestring); + } + if ($fixhour) { + $hourstring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %I', $date))); + $datestring = str_replace('HH', $hourstring, $datestring); + } + } else { + $date += (int)($timezone * 3600); + $datestring = date_format_string($date, $format, $timezone); + if ($fixday) { + $daystring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %d', $date))); + $datestring = str_replace('DD', $daystring, $datestring); + } + if ($fixhour) { + $hourstring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %I', $date))); + $datestring = str_replace('HH', $hourstring, $datestring); + } + } + + return $datestring; + } + + /** + * Given a $time timestamp in GMT (seconds since epoch), returns an array that + * represents the date in user time. + * + * @param int $time Timestamp in GMT + * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no + * dst offset is applyed {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @return array An array that represents the date in user time + */ + function usergetdate($time, $timezone) { + // Save input timezone, required for dst offset check. + $passedtimezone = $timezone; + + $timezone = get_user_timezone_offset($timezone); + + if (abs($timezone) > 13) { // Server time. + return getdate($time); + } + + // Add daylight saving offset for string timezones only, as we can't get dst for + // float values. if timezone is 99 (user default timezone), then try update dst. + if ($passedtimezone == 99 || !is_numeric($passedtimezone)) { + $time += dst_offset_on($time, $passedtimezone); + } + + $time += intval((float)$timezone * HOURSECS); + + $datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time); + + // Be careful to ensure the returned array matches that produced by getdate() above. + list ( + $getdate['month'], + $getdate['weekday'], + $getdate['yday'], + $getdate['year'], + $getdate['mon'], + $getdate['wday'], + $getdate['mday'], + $getdate['hours'], + $getdate['minutes'], + $getdate['seconds'] + ) = explode('_', $datestring); + + // Set correct datatype to match with getdate(). + $getdate['seconds'] = (int) $getdate['seconds']; + $getdate['yday'] = (int) $getdate['yday'] - 1; + $getdate['year'] = (int) $getdate['year']; + $getdate['mon'] = (int) $getdate['mon']; + $getdate['wday'] = (int) $getdate['wday']; + $getdate['mday'] = (int) $getdate['mday']; + $getdate['hours'] = (int) $getdate['hours']; + $getdate['minutes'] = (int) $getdate['minutes']; + + return $getdate; + } +} + +/** + * Class calendar_type_plugin_factory. + * + * Factory class producing required subclasses of {@link calendar_type_plugin_base}. + */ +class calendar_type_plugin_factory { + + /** + * Returns an instance of the currently used calendar type. + * + * @return calendar_type_plugin_* the created calendar_type class + * @throws coding_exception if the calendar type file could not be loaded + */ + static function factory() { + global $CFG; + + $type = self::get_calendar_type(); + $file = 'calendar/type/' . $type . '/lib.php'; + $fullpath = $CFG->dirroot . '/' . $file; + if (is_readable($fullpath)) { + require_once($fullpath); + $class = "calendar_type_plugin_$type"; + return new $class(); + } else { + throw new coding_exception("The calendar type file $file could not be initialised, check that it exists + and that the web server has permission to read it."); + } + } + + /** + * Returns a list of calendar typess available for use. + * + * @return array the list of calendar types + */ + static function get_list_of_calendar_types() { + $calendars = array(); + $calendardirs = core_component::get_plugin_list('calendartype'); + + foreach ($calendardirs as $name => $location) { + $calendars[$name] = get_string('name', "calendartype_{$name}"); + } + + return $calendars; + } + + /** + * Returns the current calendar type in use. + * + * @return string the current calendar type being used + */ + static function get_calendar_type() { + global $CFG, $USER, $SESSION, $COURSE; + + if (!empty($COURSE->id) and $COURSE->id != SITEID and !empty($COURSE->calendartype)) { // Course calendartype can override all other settings for this page. + $return = $COURSE->calendartype; + } else if (!empty($SESSION->calendartype)) { // Session calendartype can override other settings. + $return = $SESSION->calendartype; + } else if (!empty($USER->calendartype)) { + $return = $USER->calendartype; + } else if (!empty($CFG->calendartype)) { + $return = $CFG->calendartype; + } else { + $return = 'gregorian'; + } + + return $return; + } +} + diff --git a/calendarsystem/version.php b/calendar/type/gregorian/lang/en/calendartype_gregorian.php similarity index 67% rename from calendarsystem/version.php rename to calendar/type/gregorian/lang/en/calendartype_gregorian.php index 24c4d6d02a418..d6d8625746e26 100644 --- a/calendarsystem/version.php +++ b/calendar/type/gregorian/lang/en/calendartype_gregorian.php @@ -1,4 +1,5 @@ . /** - * Version details + * Strings for component 'calendar_type_plugin_gregorian', language 'en'. * - * @package calendarsystem - * @author Shamim Rezaie - * @copyright 2008 onwards Foodle Group {@link http://foodle.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package calendar_type_plugin_gregorian + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - -$version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) +$string['name'] = 'Gregorian'; +$string['pluginname'] = 'Gregorian calendar type'; diff --git a/calendar/type/gregorian/lib.php b/calendar/type/gregorian/lib.php new file mode 100644 index 0000000000000..3aa3143fe1354 --- /dev/null +++ b/calendar/type/gregorian/lib.php @@ -0,0 +1,133 @@ +. + +/** + * Handles calendar functions for the gregorian calendar. + * + * @package calendar_type_plugin_gregorian + * @author Shamim Rezaie + * @author Mark Nelson + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class calendar_type_plugin_gregorian extends calendar_type_plugin_base { + + /** + * Returns a list of all the possible days for all months. + * + * This is used to generate the select box for the days + * in the date selector elements. Some months contain more days + * than others so this function should return all possible days as + * we can not predict what month will be chosen (the user + * may have JS turned off and we need to support this situation in + * Moodle). + * + * @return array the days + */ + public function get_days() { + $days = array(); + + for ($i = 1; $i <= 31; $i++) { + $days[$i] = $i; + } + + return $days; + } + + /** + * Returns a list of all the names of the months. + * + * @return array the month names + */ + public function get_months() { + $months = array(); + + for ($i = 1; $i <= 12; $i++) { + $months[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), '%B'); + } + + return $months; + } + + /** + * Returns the minimum year of the calendar. + * + * @return int the minumum year + */ + public function get_min_year() { + return 1900; + } + + /** + * Returns the maximum year of the calendar. + * + * @return int the max year + */ + public function get_max_year() { + return 2050; + } + + /** + * Provided with a day, month, year, hour and minute in a specific + * calendar type convert it into the equivalent Gregorian date. + * + * In this function we don't need to do anything except pass the data + * back as an array. This is because the date received is Gregorian. + * + * @param int $year + * @param int $month + * @param int $day + * @param int $hour + * @param int $minute + * @return array the converted day, month, year, hour and minute. + */ + public function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0) { + $date = array(); + $date['year'] = $year; + $date['month'] = $month; + $date['day'] = $day; + $date['hour'] = $hour; + $date['minute'] = $minute; + + return $date; + } + + /** + * Provided with a day, month, year, hour and minute in a specific + * calendar type convert it into the equivalent Gregorian date. + * + * In this function we don't need to do anything except pass the data + * back as an array. This is because the date received is Gregorian. + * + * @param int $year + * @param int $month + * @param int $day + * @param int $hour + * @param int $minute + * @return array the converted day, month, year, hour and minute. + */ + public function convert_to_gregorian($year, $month, $day, $hour = 0, $minute = 0) { + $date = array(); + $date['year'] = $year; + $date['month'] = $month; + $date['day'] = $day; + $date['hour'] = $hour; + $date['minute'] = $minute; + + return $date; + } +} diff --git a/calendarsystem/hijri/version.php b/calendar/type/gregorian/version.php similarity index 59% rename from calendarsystem/hijri/version.php rename to calendar/type/gregorian/version.php index 64024e6739a2c..5b0b203e49de6 100644 --- a/calendarsystem/hijri/version.php +++ b/calendar/type/gregorian/version.php @@ -15,17 +15,15 @@ // along with Moodle. If not, see . /** - * Version details + * Version details. * - * @package calendarsystem - * @subpackage hijri - * @author Shamim Rezaie - * @copyright 2008 onwards Foodle Group {@link http://foodle.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package calendar_type_plugin_gregorian + * @copyright 2008 onwards Foodle Group {@link http://foodle.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2012120300; // Requires this Moodle version -$plugin->component = 'calendarsystem_hijri'; // Full name of the plugin (used for diagnostics) +$plugin->version = 2013062000; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2012120300; // Requires this Moodle version. +$plugin->component = 'calendartype_gregorian'; // Full name of the plugin (used for diagnostics). diff --git a/calendar/view.php b/calendar/view.php index 8995f6d395002..40a2d82a13541 100644 --- a/calendar/view.php +++ b/calendar/view.php @@ -88,8 +88,7 @@ $strcalendar = get_string('calendar', 'calendar'); -// MDL-18375, Multi-Calendar Support -if (!$CALENDARSYSTEM->checkdate($mon, $day, $yr)) { +if (!checkdate($mon, $day, $yr)) { $day = intval($now['mday']); $mon = intval($now['mon']); $yr = intval($now['year']); diff --git a/calendarsystem/admin.php b/calendarsystem/admin.php deleted file mode 100644 index f32981a6d1cbb..0000000000000 --- a/calendarsystem/admin.php +++ /dev/null @@ -1,98 +0,0 @@ -. - -require_once('../config.php'); -require_once($CFG->libdir.'/adminlib.php'); -require_once($CFG->libdir.'/tablelib.php'); - -admin_externalpage_setup('managecalendarsystems'); - -$delete = optional_param('delete', '', PARAM_PLUGIN); -$confirm = optional_param('confirm', '', PARAM_BOOL); - -/// If data submitted, then process and store. - -if (!empty($delete) and confirm_sesskey()) { - echo $OUTPUT->header(); - echo $OUTPUT->heading(get_string('type_calendarsystem_plural', 'plugin')); - - if (!$confirm) { - if (get_string_manager()->string_exists('pluginname', 'calendarsystem_' . $delete)) { - $strpluginname = get_string('pluginname', 'calendarsystem_' . $delete); - } else { - $strpluginname = $delete; - } - echo $OUTPUT->confirm(get_string('calendarsystemdeleteconfirm', 'calendarsystem', $strpluginname), - new moodle_url($PAGE->url, array('delete' => $delete, 'confirm' => 1)), - $PAGE->url); - echo $OUTPUT->footer(); - die(); - - } else { - uninstall_plugin('calendarsystem', $delete); - $a = new stdclass(); - $a->name = $delete; - $pluginlocation = get_plugin_types(); - $a->directory = $pluginlocation['calendarsystem'] . '/' . $delete; - echo $OUTPUT->notification(get_string('plugindeletefiles', '', $a), 'notifysuccess'); - echo $OUTPUT->continue_button($PAGE->url); - echo $OUTPUT->footer(); - die(); - } -} - -echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('type_calendarsystem_plural', 'plugin')); - -/// Print the table of all installed local plugins - -$table = new flexible_table('calendarsystems_administration_table'); -$table->define_columns(array('name', 'version', 'delete')); -$table->define_headers(array(get_string('plugin'), get_string('version'), get_string('delete'))); -$table->define_baseurl($PAGE->url); -$table->set_attribute('id', 'calendarsystems'); -$table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide'); -$table->setup(); - -$plugins = array(); -foreach (get_plugin_list('calendarsystem') as $plugin => $plugindir) { - if (get_string_manager()->string_exists('pluginname', 'calendarsystem_' . $plugin)) { - $strpluginname = get_string('pluginname', 'calendarsystem_' . $plugin); - } else { - $strpluginname = $plugin; - } - $plugins[$plugin] = $strpluginname; -} -collatorlib::asort($plugins); - -foreach ($plugins as $plugin => $name) { - $delete = new moodle_url($PAGE->url, array('delete' => $plugin, 'sesskey' => sesskey())); - $delete = html_writer::link($delete, get_string('delete')); - - $version = get_config('calendarsystem_' . $plugin); - if (!empty($version->version)) { - $version = $version->version; - } else { - $version = '?'; - } - - $table->add_data(array($name, $version, $delete)); -} - -$table->print_html(); -echo $OUTPUT->container(html_writer::link('index.php', get_string('checkforupdates', 'calendarsystem')), 'singlebutton'); -echo $OUTPUT->footer(); diff --git a/calendarsystem/calendarsystem.class.php b/calendarsystem/calendarsystem.class.php deleted file mode 100644 index cea0f3839db06..0000000000000 --- a/calendarsystem/calendarsystem.class.php +++ /dev/null @@ -1,69 +0,0 @@ -calendarsystem) ? 'gregorian' : $CFG->calendarsystem; // we might be in the installation process and $CFG->calendarststem might be undefined yet - } - if (file_exists("$CFG->dirroot/calendarsystem/$system/calendarsystem.php")) { - require_once("$CFG->dirroot/calendarsystem/$system/calendarsystem.php"); - $class = "calendarsystem_plugin_$system"; - return new $class; - } else { - trigger_error("$CFG->dirroot/calendarsystem/$system/calendarsystem.php does not exist"); - notify("Calendar system file $system/calendarsystem.php does not exist"); - } - } -} - -function get_list_of_calendars() { - $calendars = array(); - $calendardirs = get_list_of_plugins('calendarsystem'); - - foreach ($calendardirs as $calendar) { - $calendars[$calendar] = get_string('name', "calendarsystem_{$calendar}"); - } - - return $calendars; -} - -function current_calendarsystem_plugin() { - global $CFG, $USER, $SESSION, $COURSE; - - if (!empty($COURSE->id) and $COURSE->id != SITEID and !empty($COURSE->calendarsystem)) { // Course calendarsystem can override all other settings for this page - $return = $COURSE->calendarsystem; - - } else if (!empty($SESSION->calendarsystem)) { // Session calendarsystem can override other settings - $return = $SESSION->calendarsystem; - - } else if (!empty($USER->calendarsystem)) { - $return = $USER->calendarsystem; - - } else { - $return = $CFG->calendarsystem; - } - - return $return; -} -?> \ No newline at end of file diff --git a/calendarsystem/gregorian/calendarsystem.php b/calendarsystem/gregorian/calendarsystem.php deleted file mode 100644 index bfe480524200f..0000000000000 --- a/calendarsystem/gregorian/calendarsystem.php +++ /dev/null @@ -1,88 +0,0 @@ - \ No newline at end of file diff --git a/calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php b/calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php deleted file mode 100644 index c0df03a3f48e8..0000000000000 --- a/calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php b/calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php deleted file mode 100644 index 2cb6e5f6aed74..0000000000000 --- a/calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/calendarsystem/gregorian/version.php b/calendarsystem/gregorian/version.php deleted file mode 100644 index ae02452791356..0000000000000 --- a/calendarsystem/gregorian/version.php +++ /dev/null @@ -1,31 +0,0 @@ -. - -/** - * Version details - * - * @package calendarsystem - * @subpackage gregorian - * @author Shamim Rezaie - * @copyright 2008 onwards Foodle Group {@link http://foodle.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$plugin->version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2012120300; // Requires this Moodle version -$plugin->component = 'calendarsystem_gregorian'; // Full name of the plugin (used for diagnostics) diff --git a/calendarsystem/hijri/calendarsystem.php b/calendarsystem/hijri/calendarsystem.php deleted file mode 100644 index 54ea267cf6aab..0000000000000 --- a/calendarsystem/hijri/calendarsystem.php +++ /dev/null @@ -1,250 +0,0 @@ -to_gregorian(1, $m+1, $y); - $temp = $this->from_gregorian($temp['day']-1, $temp['month'], $temp['year']); - return $temp['day']; - } - - public function usergetdate($time, $timezone=99) { - $date = usergetdate_old($time); - $new_date = $this->from_gregorian($date["mday"], $date["mon"], $date["year"]); - - $date["month"] = get_string("month{$new_date['month']}", 'calendarsystem_hijri'); - $date["weekday"] = get_string("weekday{$date['wday']}", 'calendarsystem_hijri'); - $date["yday"] = null; - $date["year"] = $new_date['year']; - $date["mon"] = $new_date['month']; - $date["mday"] = $new_date['day']; - - return $date; - } - - public function checkdate($m, $d, $y) - { - $temp = $this->to_gregorian($d, $m, $y); - $temp = $this->from_gregorian($temp['day'], $temp['month'], $temp['year']); - return ($temp['day'] == $d) && ($temp['month'] == $m) && ($temp['year'] == $y); - } - - public function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { - $new_date = $this->to_gregorian($day, $month, $year); - return make_timestamp_old($new_date['year'], $new_date['month'], $new_date['day'], $hour, $minute, $second, $timezone, $applydst); - } - - public function userdate($date, $format='', $timezone=99, $fixday = true, $fixhour = true) { - static $amstring = null, $pmstring = null, $AMstring = null, $PMstring = null; - - if (!$amstring) { - $amstring = get_string('am', 'calendarsystem_hijri'); - $pmstring = get_string('pm', 'calendarsystem_hijri'); - $AMstring = get_string('am_caps', 'calendarsystem_hijri'); - $PMstring = get_string('pm_caps', 'calendarsystem_hijri'); - } - - if (empty($format)) { - $format = get_string('strftimedaydatetime'); - } - - if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed. - $fixday = false; - } - - $date_ = $this->usergetdate($date); - //this is not sufficient code, change it. but it works correctly. - $format = str_replace( array( - "%a", - "%A", - "%b", - "%B", - "%d", - "%m", - "%y", - "%Y", - "%p", - "%P" - ), - array( - $date_["weekday"], - $date_["weekday"], - $date_["month"], - $date_["month"], - (($date_["mday"] < 10 && !$fixday) ? '0' : '') . $date_["mday"], - ($date_["mon"] < 10 ? '0' : '') . $date_["mon"], - $date_["year"] % 100, - $date_["year"], - ($date_["hours"] < 12 ? $AMstring : $PMstring), - ($date_["hours"] < 12 ? $amstring : $pmstring) - ), - $format); - - return userdate_old($date, $format, $timezone, $fixday, $fixhour); - } - - public function today() - { - list($g_y, $g_m, $g_d) = explode( "-", date("Y-m-d")); - $today = $this->from_gregorian((int)$g_d, (int)$g_m, (int)$g_y); - - return array($today['month'], $today['day'], $today['year']); - } - - public function get_month_names() - { - $months = array(); - - for ($i=1; $i<=12; $i++) { - $months[$i] = get_string("month{$i}", 'calendarsystem_hijri'); - } - - return $months; - } - - public function get_min_year() - { - return 1390; - } - - public function get_max_year() - { - return 1440; - } - - public function gmmktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { - if (empty($day) || empty($month) || empty($year)) { - $today = $this->today(); - if (empty($day)) { - $day = $today['day']; - } - if (empty($month)) { - $month = $today['month']; - } - if (empty($year)) { - $year = $today['year']; - } - } - - $g_date = $this->to_gregorian($day, $month, $year); - - return gmmktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); - } - - public function mktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { - if (empty($day) || empty($month) || empty($year)) { - $today = $this->today(); - - if (empty($day)) { - $day = $today['day']; - } - if (empty($month)) { - $month = $today['month']; - } - if (empty($year)) { - $year = $today['year']; - } - } - - $g_date = $this->to_gregorian($day, $month, $year); - - return mktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); - } - - public function dayofweek($day, $month, $year) { - $g_date = $this->to_gregorian($day, $month, $year); - return intval(date('w', mktime(12, 0, 0, $g_date['month'], $g_date['day'], $g_date['year']))); - } - - private $ISLAMIC_EPOCH = 1948439.5; - private $GREGORIAN_EPOCH = 1721425.5; - - // LEAP_GREGORIAN -- Is a given year in the Gregorian calendar a leap year ? - private function leap_gregorian($year) - { - return (($year % 4) == 0) && - (!((($year % 100) == 0) && (($year % 400) != 0))); - } - - // GREGORIAN_TO_JD -- Determine Julian day number from Gregorian calendar date - private function gregorian_to_jd($year, $month, $day) - { - return ($this->GREGORIAN_EPOCH - 1) + - (365 * ($year - 1)) + - floor(($year - 1) / 4) + - (-floor(($year - 1) / 100)) + - floor(($year - 1) / 400) + - floor((((367 * $month) - 362) / 12) + - (($month <= 2) ? 0 : ($this->leap_gregorian($year) ? -1 : -2) - ) + - $day); - } - - // JD_TO_GREGORIAN -- Calculate Gregorian calendar date from Julian day - private function jd_to_gregorian($jd) { - $wjd = floor($jd - 0.5) + 0.5; - $depoch = $wjd - $this->GREGORIAN_EPOCH; - $quadricent = floor($depoch / 146097); - $dqc = $depoch % 146097; - $cent = floor($dqc / 36524); - $dcent = $dqc % 36524; - $quad = floor($dcent / 1461); - $dquad = $dcent % 1461; - $yindex = floor($dquad / 365); - $year = ($quadricent * 400) + ($cent * 100) + ($quad * 4) + $yindex; - if (!(($cent == 4) || ($yindex == 4))) { - $year++; - } - $yearday = $wjd - $this->gregorian_to_jd($year, 1, 1); - $leapadj = (($wjd < $this->gregorian_to_jd($year, 3, 1)) ? 0 : ($this->leap_gregorian($year) ? 1 : 2)); - $month = floor(((($yearday + $leapadj) * 12) + 373) / 367); - $day = ($wjd - $this->gregorian_to_jd($year, $month, 1)) + 1; - - return array('year' => $year, - 'month' => $month, - 'day' => $day); - } - - - private function islamic_to_jd($year, $month, $day) - { - return ($day + - ceil(29.5 * ($month - 1)) + - ($year - 1) * 354 + - floor((3 + (11 * $year)) / 30) + - $this->ISLAMIC_EPOCH) - 1; - } - - - - // JD_TO_ISLAMIC -- Calculate Islamic date from Julian day - private function jd_to_islamic($jd) - { - $jd = floor($jd) + 0.5; - $year = floor(((30 * ($jd - $this->ISLAMIC_EPOCH)) + 10646) / 10631); - $month = min(12, - ceil(($jd - (29 + $this->islamic_to_jd($year, 1, 1))) / 29.5) + 1); - $day = ($jd - $this->islamic_to_jd($year, $month, 1)) + 1; - - return array('year' => $year, - 'month' => $month, - 'day' => $day); - } - - private function from_gregorian($g_d, $g_m, $g_y) { - $jd = $this->gregorian_to_jd($g_y, $g_m, $g_d); - return $this->jd_to_islamic($jd); - } - - private function to_gregorian($i_d, $i_m, $i_y) { - $jd = $this->islamic_to_jd($i_y, $i_m, $i_d); - return $this->jd_to_gregorian($jd); - } -} -?> \ No newline at end of file diff --git a/calendarsystem/hijri/lang/en/calendarsystem_hijri.php b/calendarsystem/hijri/lang/en/calendarsystem_hijri.php deleted file mode 100644 index 04f02d017fdde..0000000000000 --- a/calendarsystem/hijri/lang/en/calendarsystem_hijri.php +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/calendarsystem/hijri/lang/fa/calendarsystem_hijri.php b/calendarsystem/hijri/lang/fa/calendarsystem_hijri.php deleted file mode 100644 index 233d14979a229..0000000000000 --- a/calendarsystem/hijri/lang/fa/calendarsystem_hijri.php +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/calendarsystem/index.php b/calendarsystem/index.php deleted file mode 100644 index 839795664be95..0000000000000 --- a/calendarsystem/index.php +++ /dev/null @@ -1,175 +0,0 @@ -libdir.'/adminlib.php'); // various admin-only functions -require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions -require_once($CFG->libdir.'/pluginlib.php'); // available updates notifications -require_once('updatechecker.php'); // available updates notifications - -$fetchupdates = optional_param('fetchupdates', 0, PARAM_BOOL); - -// Check some PHP server settings - -$PAGE->set_url('/calendarsystem/index.php'); -$PAGE->set_pagelayout('admin'); // Set a default pagelayout - -$version = null; -require("$CFG->dirroot/calendarsystem/version.php"); -// Check version of calendarsystem code on disk - -$PAGE->set_context(context_system::instance()); - -// Check for valid admin user - no guest autologin -require_login(0, false); -$context = context_system::instance(); -require_capability('moodle/site:config', $context); - - -// Everything should now be set up, and the user is an admin - - -// Available updates for Moodle core -$updateschecker = calendarsystem_update_checker::instance(); -$availableupdates = array(); -$availableupdates['core'] = $updateschecker->get_update_info('core'); - -// Available updates for calendar system plugins -$calendars = get_plugin_list('calendarsystem'); -foreach ($calendars as $calendar => $calendarrootdir) { - $availableupdates[$calendar] = $updateschecker->get_update_info('calendarsystem_'.$calendar); -} -/* -$pluginman = plugin_manager::instance(); -foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) { - foreach ($plugintypeinstances as $pluginname => $plugininfo) { - if (!empty($plugininfo->availableupdates)) { - foreach ($plugininfo->availableupdates as $pluginavailableupdate) { - if ($pluginavailableupdate->version > $plugininfo->versiondisk) { - if (!isset($availableupdates[$plugintype.'_'.$pluginname])) { - $availableupdates[$plugintype.'_'.$pluginname] = array(); - } - $availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate; - } - } - } - } -} -*/ -// The timestamp of the most recent check for available updates -$availableupdatesfetch = $updateschecker->get_last_timefetched(); - -//admin_externalpage_setup('adminnotifications'); - -if ($fetchupdates) { - require_sesskey(); - $updateschecker->fetch(); - redirect($PAGE->url); -} - -$strupdatecheck = get_string('updatecheck', 'calendarsystem'); -$PAGE->navbar->add($strupdatecheck); - -echo $OUTPUT->header(); -echo available_updates($availableupdates, $availableupdatesfetch); - -echo $OUTPUT->footer(); - - -/////////////////////////////////////////////////////////////////////////////////////// - /** - * Displays the info about available Moodle core and plugin updates - * - * The structure of the $updates param has changed since 2.4. It contains not only updates - * for the core itself, but also for all other installed plugins. - * - * @param array|null $updates array of (string)component => array of calendarsystem_update_info objects or null - * @param int|null $fetch timestamp of the most recent updates fetch or null (unknown) - * @return string - */ - function available_updates($updates, $fetch) { - global $OUTPUT; - - $updateinfo = $OUTPUT->box_start('generalbox adminwarning calendarsystemupdatesinfo'); - $someupdateavailable = false; - if (is_array($updates)) { - if (is_array($updates['core'])) { - $someupdateavailable = true; - $updateinfo .= $OUTPUT->heading(get_string('updateavailable', 'calendarsystem'), 3); - foreach ($updates['core'] as $update) { - $updateinfo .= moodle_available_update_info($update); - } - } - unset($updates['core']); - // If something has left in the $updates array now, it is updates for plugins. - if (!empty($updates)) { - foreach ($updates as $pluginname=>$pluginupdates) { - if (is_array($pluginupdates)) { - $someupdateavailable = true; - $updateinfo .= $OUTPUT->heading(get_string('updateavailableforplugin', 'calendarsystem', get_string('name', 'calendarsystem_'.$pluginname)), 3); - - foreach ($pluginupdates as $update) { - $updateinfo .= moodle_available_update_info($update); - } - } - } - } - } - - if (!$someupdateavailable) { - $now = time(); - if ($fetch and ($fetch <= $now) and ($now - $fetch < HOURSECS)) { - $updateinfo .= $OUTPUT->heading(get_string('updateavailablenot', 'calendarsystem'), 3); - } - } - - $updateinfo .= $OUTPUT->container_start('checkforupdates'); - $updateinfo .= $OUTPUT->single_button(new moodle_url('', array('fetchupdates' => 1)), get_string('checkforupdates', 'calendarsystem')); - if ($fetch) { - $updateinfo .= $OUTPUT->container(get_string('checkforupdateslast', 'core_plugin', - userdate($fetch, get_string('strftimedatetime', 'core_langconfig')))); - } - $updateinfo .= $OUTPUT->container_end(); - - $updateinfo .= $OUTPUT->box_end(); - - return $updateinfo; - } - - - /** - * Helper method to render the information about the available Moodle update - * - * @param calendarsystem_update_info $updateinfo information about the available Moodle core update - */ - function moodle_available_update_info(calendarsystem_update_info $updateinfo) { - global $OUTPUT; - - $boxclasses = 'moodleupdateinfo'; - $info = array(); - - if (isset($updateinfo->version)) { - $info[] = html_writer::tag('span', get_string('updateavailable_version', 'calendarsystem', $updateinfo->version), - array('class' => 'info version')); - } - - if (isset($updateinfo->download)) { - $info[] = html_writer::link($updateinfo->download, get_string('download'), array('class' => 'info download')); - } - - if (isset($updateinfo->url)) { - $info[] = html_writer::link($updateinfo->url, get_string('updateavailable_moreinfo', 'calendarsystem'), - array('class' => 'info more')); - } - - $box = $OUTPUT->box_start($boxclasses); - $box .= $OUTPUT->box(implode(html_writer::tag('span', ' - ', array('class' => 'separator')), $info), ''); - $box .= $OUTPUT->box_end(); - - return $box; - } -/////////////////////////////////////////////////////////////////////////////////////// - - - diff --git a/calendarsystem/jalali/calendarsystem.php b/calendarsystem/jalali/calendarsystem.php deleted file mode 100644 index dd5e435398df8..0000000000000 --- a/calendarsystem/jalali/calendarsystem.php +++ /dev/null @@ -1,289 +0,0 @@ -isleap_solar($y)) - return 30; - - return 29; - } - - public function usergetdate($time, $timezone=99) { - $date = usergetdate_old($time); - $new_date = $this->from_gregorian($date["mday"], $date["mon"], $date["year"]); - - $date["month"] = get_string("month{$new_date['month']}", 'calendarsystem_jalali'); - $date["weekday"] = get_string("weekday{$date['wday']}", 'calendarsystem_jalali'); - $date["yday"] = null; - $date["year"] = $new_date['year']; - $date["mon"] = $new_date['month']; - $date["mday"] = $new_date['day']; - - return $date; -} - - public function checkdate($m, $d, $y) - { - // $m not in 1..12 or $d not in 1..31 - if ($m < 1 or 12 < $m or $d < 1 or $d > 31) - return false; - - // $m in 1..6 and at this line $d in 1..31 - if ($m < 7) - return true; - - // $m in 7..11 and possible value for $d is in 0..31 (but 31 is invalid) - if ($m != 12) - if ($d == 31) { - return false; - } else { - return true; - } - - // $m is 12 - if ($this->isleap_solar($y)) - { - if ($d == 31) - return false; - } - else // $y is not leap year. - if ($d == 31) - return false; - - return true; - } - - public function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { - $new_date = $this->to_gregorian($day, $month, $year); - return make_timestamp_old($new_date['year'], $new_date['month'], $new_date['day'], $hour, $minute, $second, $timezone, $applydst); - } - - public function userdate($date, $format='', $timezone=99, $fixday = true, $fixhour = true) { - static $amstring = null, $pmstring = null, $AMstring = null, $PMstring = null; - - if (!$amstring) { - $amstring = get_string('am', 'calendarsystem_jalali'); - $pmstring = get_string('pm', 'calendarsystem_jalali'); - $AMstring = get_string('am_caps', 'calendarsystem_jalali'); - $PMstring = get_string('pm_caps', 'calendarsystem_jalali'); - } - - if (empty($format)) { - $format = get_string('strftimedaydatetime'); - } - - if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed. - $fixday = false; - } - - $date_ = $this->usergetdate($date); - //this is not sufficient code, change it. but it works correctly. - $format = str_replace( array( - "%a", - "%A", - "%b", - "%B", - "%d", - "%m", - "%y", - "%Y", - "%p", - "%P" - ), - array( - $date_["weekday"], - $date_["weekday"], - $date_["month"], - $date_["month"], - (($date_["mday"] < 10 && !$fixday) ? '0' : '') . $date_["mday"], - ($date_["mon"] < 10 ? '0' : '') . $date_["mon"], - $date_["year"] % 100, - $date_["year"], - ($date_["hours"] < 12 ? $AMstring : $PMstring), - ($date_["hours"] < 12 ? $amstring : $pmstring) - ), - $format); - - return userdate_old($date, $format, $timezone, $fixday, $fixhour); - } - - public function today() - { - list($g_y, $g_m, $g_d) = explode( "-", date("Y-m-d")); - $today = $this->from_gregorian((int)$g_d, (int)$g_m, (int)$g_y); - - return array($today['month'], $today['day'], $today['year']); - } - - public function get_month_names() - { - $months = array(); - - for ($i=1; $i<=12; $i++) { - $months[$i] = get_string("month{$i}", 'calendarsystem_jalali'); - } - - return $months; - } - - public function get_min_year() - { - return 1350; - } - - public function get_max_year() - { - return 1400; - } - - public function gmmktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { - if (empty($day) || empty($month) || empty($year)) { - $today = $this->today(); - if (empty($day)) { - $day = $today['day']; - } - if (empty($month)) { - $month = $today['month']; - } - if (empty($year)) { - $year = $today['year']; - } - } - - $g_date = $this->to_gregorian($day, $month, $year); - - return gmmktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); - } - - public function mktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) { - if (empty($day) || empty($month) || empty($year)) { - $today = $this->today(); - - if (empty($day)) { - $day = $today['day']; - } - if (empty($month)) { - $month = $today['month']; - } - if (empty($year)) { - $year = $today['year']; - } - } - - $g_date = $this->to_gregorian($day, $month, $year); - - return mktime($hour, $minute, $second, $g_date['month'], $g_date['day'], $g_date['year']); - } - - public function dayofweek($day, $month, $year) { - $g_date = $this->to_gregorian($day, $month, $year); - return intval(date('w', mktime(12, 0, 0, $g_date['month'], $g_date['day'], $g_date['year']))); - } - - - private $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); - private $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29); - - private function isleap_solar($year) { - /* 33-year cycles, it better matches Iranian rules */ - return (($year+16)%33+33)%33*8%33 < 8; - } - - private function from_gregorian($g_d, $g_m, $g_y) { - $gy = $g_y-1600; - $gm = $g_m-1; - $gd = $g_d-1; - - $g_day_no = 365*$gy+$this->div($gy+3,4)-$this->div($gy+99,100)+$this->div($gy+399,400); - - for ($i=0; $i < $gm; ++$i) - $g_day_no += $this->g_days_in_month[$i]; - if ($gm>1 && (($gy%4==0 && $gy%100!=0) || ($gy%400==0))) - /* leap and after Feb */ - ++$g_day_no; - $g_day_no += $gd; - - $j_day_no = $g_day_no-79; - - $j_np = $this->div($j_day_no, 12053); - $j_day_no %= 12053; - - $jy = 979+33*$j_np+4*$this->div($j_day_no,1461); - - $j_day_no %= 1461; - - if ($j_day_no >= 366) { - $jy += $this->div($j_day_no-1, 365); - $j_day_no = ($j_day_no-1)%365; - } - - for ($i = 0; $i < 11 && $j_day_no >= $this->j_days_in_month[$i]; ++$i) { - $j_day_no -= $this->j_days_in_month[$i]; - } - $jm = $i+1; - $jd = $j_day_no+1; - - - return array('year' => $jy, - 'month' => $jm, - 'day' => $jd); - } - - private function to_gregorian($j_d, $j_m, $j_y) { - $jy = $j_y-979; - $jm = $j_m-1; - $jd = $j_d-1; - - $j_day_no = 365*$jy + $this->div($jy, 33)*8 + $this->div($jy%33+3, 4); - for ($i=0; $i < $jm; ++$i) - $j_day_no += $this->j_days_in_month[$i]; - - $j_day_no += $jd; - - $g_day_no = $j_day_no+79; - - $gy = 1600 + 400*$this->div($g_day_no, 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */ - $g_day_no = $g_day_no % 146097; - - $leap = true; - if ($g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */ - { - $g_day_no--; - $gy += 100*$this->div($g_day_no, 36524); /* 36524 = 365*100 + 100/4 - 100/100 */ - $g_day_no = $g_day_no % 36524; - - if ($g_day_no >= 365) - $g_day_no++; - else - $leap = false; - } - - $gy += 4*$this->div($g_day_no, 1461); /* 1461 = 365*4 + 4/4 */ - $g_day_no %= 1461; - - if ($g_day_no >= 366) { - $leap = false; - - $g_day_no--; - $gy += $this->div($g_day_no, 365); - $g_day_no = $g_day_no % 365; - } - - for ($i = 0; $g_day_no >= $this->g_days_in_month[$i] + ($i == 1 && $leap); $i++) - $g_day_no -= $this->g_days_in_month[$i] + ($i == 1 && $leap); - $gm = $i+1; - $gd = $g_day_no+1; - - return array('year' => $gy, - 'month' => $gm, - 'day' => $gd); - } - - private function div($a,$b) { - return (int) ($a / $b); - } -} -?> \ No newline at end of file diff --git a/calendarsystem/jalali/lang/en/calendarsystem_jalali.php b/calendarsystem/jalali/lang/en/calendarsystem_jalali.php deleted file mode 100644 index 64a7a86cef14a..0000000000000 --- a/calendarsystem/jalali/lang/en/calendarsystem_jalali.php +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/calendarsystem/jalali/lang/fa/calendarsystem_jalali.php b/calendarsystem/jalali/lang/fa/calendarsystem_jalali.php deleted file mode 100644 index 35d662c7c9fcf..0000000000000 --- a/calendarsystem/jalali/lang/fa/calendarsystem_jalali.php +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/calendarsystem/jalali/version.php b/calendarsystem/jalali/version.php deleted file mode 100644 index bb397749d6495..0000000000000 --- a/calendarsystem/jalali/version.php +++ /dev/null @@ -1,31 +0,0 @@ -. - -/** - * Version details - * - * @package calendarsystem - * @subpackage jalali - * @author Shamim Rezaie - * @copyright 2008 onwards Foodle Group {@link http://foodle.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$plugin->version = 2013011900; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2012120300; // Requires this Moodle version -$plugin->component = 'calendarsystem_jalali'; // Full name of the plugin (used for diagnostics) diff --git a/calendarsystem/updatechecker.php b/calendarsystem/updatechecker.php deleted file mode 100644 index cc6b69da3c990..0000000000000 --- a/calendarsystem/updatechecker.php +++ /dev/null @@ -1,341 +0,0 @@ - (string)version list of additional plugins deployed at this site */ - protected $currentplugins = array(); - - /** - * Direct initiation not allowed, use the factory method {@link self::instance()} - */ - protected function __construct() { - } - - /** - * Sorry, this is singleton - */ - protected function __clone() { - } - - /** - * Factory method for this class - * - * @return calendarsystem_update_checker the singleton instance - */ - public static function instance() { - if (is_null(self::$singletoninstance)) { - self::$singletoninstance = new self(); - } - return self::$singletoninstance; - } - - /** - * Returns the timestamp of the last execution of {@link fetch()} - * - * @return int|null null if it has never been executed or we don't known - */ - public function get_last_timefetched() { - - $this->restore_response(); - - if (!empty($this->recentfetch)) { - return $this->recentfetch; - - } else { - return null; - } - } - - /** - * Fetches the available update status from the remote site - * - * @throws available_update_checker_exception - */ - public function fetch() { - $response = $this->get_response(); - $this->validate_response($response); - $this->store_response($response); - } - - /** - * Returns the available update information for the given component - * - * This method returns null if the most recent response does not contain any information - * about it. The returned structure is an array of available updates for the given - * component. Each update info is an object with at least one property called - * 'version'. Other possible properties are 'release', 'maturity', 'url' and 'downloadurl'. - * - * For the 'core' component, the method returns real updates only (those with higher version). - * For all other components, the list of all known remote updates is returned and the caller - * (usually the {@link plugin_manager}) is supposed to make the actual comparison of versions. - * - * @param string $component frankenstyle - * @param array $options with supported keys 'minmaturity' and/or 'notifybuilds' - * @return null|array null or array of calendarsystem_update_info objects - */ - public function get_update_info($component, array $options = array()) { - - if ($component == 'core') { - $this->load_current_environment(); - } - - $this->restore_response(); - - if (empty($this->recentresponse['updates'][$component])) { - return null; - } - - $updates = array(); - foreach ($this->recentresponse['updates'][$component] as $info) { - $update = new calendarsystem_update_info($component, $info); - if ($update->version <= $this->currentversion) { - continue; - } - $updates[] = $update; - } - - if (empty($updates)) { - return null; - } - - return $updates; - } - - /** - * Makes cURL request to get data from the remote site - * - * @return string raw request result - * @throws calendarsystem_update_checker_exception - */ - protected function get_response() { - global $CFG; - require_once($CFG->libdir.'/filelib.php'); - - $curl = new curl(array('proxy' => true)); - $response = $curl->post($this->prepare_request_url(), $this->prepare_request_params()); - $curlerrno = $curl->get_errno(); - if (!empty($curlerrno)) { - throw new calendarsystem_update_checker_exception('err_response_curl', 'cURL error '.$curlerrno.': '.$curl->error); - } - $curlinfo = $curl->get_info(); - if ($curlinfo['http_code'] != 200) { - throw new calendarsystem_update_checker_exception('err_response_http_code', $curlinfo['http_code']); - } - return $response; - } - -/////////////////////////// -// ino ezafe karde boodam - /** - * Makes sure the response is valid, has correct API format etc. - * - * @param string $response raw response as returned by the {@link self::get_response()} - * @throws calendarsystem_update_checker_exception - */ - protected function validate_response($response) { - - $response = $this->decode_response($response); - - if (empty($response)) { - throw new calendarsystem_update_checker_exception('err_response_empty'); - } - - if (empty($response['status']) or $response['status'] !== 'OK') { - throw new calendarsystem_update_checker_exception('err_response_status', $response['status']); - } - } - - /* Decodes the raw string response from the update notifications provider - * - * @param string $response as returned by {@link self::get_response()} - * @return array decoded response structure - */ - protected function decode_response($response) { - return json_decode($response, true); - } - - /** - * Stores the valid fetched response for later usage - * - * This implementation uses the config_plugins table as the permanent storage. - * - * @param string $response raw valid data returned by {@link self::get_response()} - */ - protected function store_response($response) { - - set_config('recentfetch', time(), 'calendarsystem_plugin'); - set_config('recentresponse', $response, 'calendarsystem_plugin'); - - $this->restore_response(true); - } - - /** - * Loads the most recent raw response record we have fetched - * - * After this method is called, $this->recentresponse is set to an array. If the - * array is empty, then either no data have been fetched yet or the fetched data - * do not have expected format (and thence they are ignored and a debugging - * message is displayed). - * - * This implementation uses the config_plugins table as the permanent storage. - * - * @param bool $forcereload reload even if it was already loaded - */ - protected function restore_response($forcereload = false) { - - if (!$forcereload and !is_null($this->recentresponse)) { - // we already have it, nothing to do - return; - } - - $config = get_config('calendarsystem_plugin'); - - if (!empty($config->recentresponse) and !empty($config->recentfetch)) { - try { - $this->validate_response($config->recentresponse); - $this->recentfetch = $config->recentfetch; - $this->recentresponse = $this->decode_response($config->recentresponse); - } catch (calendarsystem_update_checker_exception $e) { - // The server response is not valid. Behave as if no data were fetched yet. - // This may happen when the most recent update info (cached locally) has been - // fetched with the previous branch of Moodle (like during an upgrade from 2.x - // to 2.y) or when the API of the response has changed. - $this->recentresponse = array(); - } - - } else { - $this->recentresponse = array(); - } - } - - /** - * Returns the URL to send update requests to - * - * @return string URL - */ - protected function prepare_request_url() { - return 'http://foodle.org/calendarsystem/api/updates.php'; - } - - /** - * Sets the properties currentversion, currentrelease, currentbranch and currentplugins - * - * @param bool $forcereload - */ - protected function load_current_environment($forcereload=false) { - global $CFG; - - if (!is_null($this->currentversion) and !$forcereload) { - // nothing to do - return; - } - - $version = null; - $plugin = new stdClass(); - - include($CFG->dirroot.'/calendarsystem/version.php'); - $this->currentversion = $version; - - $calendars = get_plugin_list('calendarsystem'); - - foreach ($calendars as $calendar => $calendarrootdir) { - include($calendarrootdir.'/version.php'); - $this->currentplugins[$calendar] = $plugin->version; - } - } - - /** - * Returns the list of HTTP params to be sent to the updates provider URL - * - * @return array of (string)param => (string)value - */ - protected function prepare_request_params() { - global $CFG; - - $this->load_current_environment(); -// $this->restore_response(); - - $params = array(); - $params['format'] = 'json'; - - if (isset($this->currentversion)) { - $params['version'] = $this->currentversion; - } else { - throw new coding_exception('Main calendarsystem version must be already known here'); - } - - $plugins = array(); - foreach ($this->currentplugins as $plugin => $version) { - $plugins[] = $plugin.'@'.$version; - } - if (!empty($plugins)) { - $params['plugins'] = implode(',', $plugins); - } - - $params['url'] = $CFG->wwwroot; - - return $params; - } - -} - -/** - * Defines the structure of objects returned by {@link calendarsystem_update_checker::get_update_info()} - */ -class calendarsystem_update_info { - - /** @var string frankenstyle component name */ - public $component; - /** @var int the available version of the component */ - public $version; - /** @var string|null optional URL of a page with more info about the update */ - public $url = null; - /** @var string|null optional URL of a ZIP package that can be downloaded and installed */ - public $download = null; - /** @var string|null if self::download is set, then this must be the MD5 hash of the ZIP */ - public $downloadmd5 = null; - - /** - * Creates new instance of the class - * - * The $info array must provide at least the 'version' value and optionally all other - * values to populate the object's properties. - * - * @param string $name the frankenstyle component name - * @param array $info associative array with other properties - */ - public function __construct($name, array $info) { - $this->component = $name; - foreach ($info as $k => $v) { - if (property_exists('calendarsystem_update_info', $k) and $k != 'component') { - $this->$k = $v; - } - } - } -} -?> \ No newline at end of file diff --git a/course/edit_form.php b/course/edit_form.php index 983a7e0fb7547..ca311ef40831f 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -6,12 +6,18 @@ require_once($CFG->libdir.'/completionlib.php'); require_once($CFG->libdir. '/coursecatlib.php'); +/** + * The form for handling editing a course. + */ class course_edit_form extends moodleform { protected $course; protected $context; + /** + * Form definition. + */ function definition() { - global $USER, $CFG, $DB, $PAGE; + global $CFG, $PAGE; $mform = $this->_form; $PAGE->requires->yui_module('moodle-course-formatchooser', 'M.course.init_formatchooser', @@ -38,8 +44,7 @@ function definition() { $this->course = $course; $this->context = $context; -/// form definition with new course defaults -//-------------------------------------------------------------------------------- + // Form definition with new course defaults. $mform->addElement('header','general', get_string('general', 'form')); $mform->addElement('hidden', 'returnto', null); @@ -247,10 +252,8 @@ function definition() { $mform->setDefault('enablecompletion', 0); } -//-------------------------------------------------------------------------------- enrol_course_edit_form($mform, $course, $context); -//-------------------------------------------------------------------------------- $mform->addElement('header','groups', get_string('groupsettingsheader', 'group')); $choices = array(); @@ -270,17 +273,15 @@ function definition() { $options[0] = get_string('none'); $mform->addElement('select', 'defaultgroupingid', get_string('defaultgrouping', 'group'), $options); -//-------------------------------------------------------------------------------- - // MDL-18375, Multi-Calendar Support + // Multi-Calendar Support - see MDL-18375 $mform->addElement('header','', get_string('calendar', 'calendar')); - $calendarsystems = array(); - $calendarsystems[''] = get_string('forceno'); - $calendarsystems += get_list_of_calendars(); - $mform->addElement('select', 'calendarsystem', get_string('forcecalendarsystem', 'calendarsystem'), $calendarsystems); + $calendartypes = array(); + $calendartypes[''] = get_string('forceno'); + $calendartypes += calendar_type_plugin_factory::get_list_of_calendar_types(); + $mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendartypes); -/// customizable role names in this course -//-------------------------------------------------------------------------------- + // Customizable role names in this course. $mform->addElement('header','rolerenaming', get_string('rolerenaming')); $mform->addHelpButton('rolerenaming', 'rolerenaming'); @@ -293,17 +294,18 @@ function definition() { } } -//-------------------------------------------------------------------------------- $this->add_action_buttons(); -//-------------------------------------------------------------------------------- + $mform->addElement('hidden', 'id', null); $mform->setType('id', PARAM_INT); -/// finally set the current form data -//-------------------------------------------------------------------------------- + // Finally set the current form data $this->set_data($course); } + /** + * Fill in the current page data for this course. + */ function definition_after_data() { global $DB; @@ -334,7 +336,13 @@ function definition_after_data() { } } -/// perform some extra moodle validation + /** + * Validation. + * + * @param array $data + * @param array $files + * @return array the errors that were found + */ function validation($data, $files) { global $DB, $CFG; diff --git a/enrol/manual/ajax.php b/enrol/manual/ajax.php index 6fcdb8dd1f8a8..c1a6f80c9b374 100644 --- a/enrol/manual/ajax.php +++ b/enrol/manual/ajax.php @@ -113,10 +113,8 @@ break; case 3: default: - // MDL-18375, Multi-Calendar Support - $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); - $today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); + $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); $timestart = $today; break; } diff --git a/enrol/manual/lib.php b/enrol/manual/lib.php index 03b2a9883c18b..10e12e1e4b011 100644 --- a/enrol/manual/lib.php +++ b/enrol/manual/lib.php @@ -230,10 +230,8 @@ public function get_manual_enrol_button(course_enrolment_manager $manager) { if ($startdate > 0) { $startdateoptions[2] = get_string('coursestart') . ' (' . userdate($startdate, $timeformat) . ')'; } - // MDL-18375, Multi-Calendar Support - $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); - $today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); + $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); $startdateoptions[3] = get_string('today') . ' (' . userdate($today, $timeformat) . ')' ; $defaultduration = $instance->enrolperiod > 0 ? $instance->enrolperiod / 86400 : ''; diff --git a/enrol/manual/manage.php b/enrol/manual/manage.php index 96ac9de6650bc..7d91e4b6017ba 100644 --- a/enrol/manual/manage.php +++ b/enrol/manual/manage.php @@ -92,11 +92,8 @@ // Build the list of options for the starting from dropdown. $timeformat = get_string('strftimedatefullshort'); - -// MDL-18375, Multi-Calendar Support -$calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); $today = time(); -$today = $calendarsystem_gregorian->make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); +$today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); // Enrolment start. $basemenu = array(); diff --git a/lang/en/admin.php b/lang/en/admin.php index d230f6755c1f2..ef68ec963b617 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -570,8 +570,9 @@ $string['guestroleid'] = 'Role for guest'; $string['guestroleid_help'] = 'This role is automatically assigned to the guest user. It is also temporarily assigned to not enrolled users that enter the course via guest enrolment plugin.'; $string['helpadminseesall'] = 'Do admins see all calendar events or just those that apply to themselves?'; -$string['helpcalendarsettings'] = 'Configure various calendar and date/time-related aspects of Moodle'; $string['helpcalendarcustomexport'] = 'Enable custom date range export option in calendar exports. Calendar exports must be enabled before this is effective.'; +$string['helpcalendarsettings'] = 'Configure various calendar and date/time-related aspects of Moodle'; +$string['helpcalendartype'] = 'This is the calendar type that will be used throughout your site.'; $string['helpexportlookahead'] = 'How many days in the future does the calendar look for events during export for the custom export option?'; $string['helpexportlookback'] = 'How many days in the past does the calendar look for events during export for the custom export option?'; $string['helpforcetimezone'] = 'You can allow users to individually select their timezone, or force a timezone for everyone.'; diff --git a/lang/en/calendar.php b/lang/en/calendar.php index 75d51b9dcb693..7a6a6aff49459 100644 --- a/lang/en/calendar.php +++ b/lang/en/calendar.php @@ -93,6 +93,7 @@ $string['exportbutton'] = 'Export'; $string['exportcalendar'] = 'Export calendar'; $string['for'] = 'for'; +$string['forcecalendartype'] = 'Force calendar'; $string['fri'] = 'Fri'; $string['friday'] = 'Friday'; $string['generateurlbutton'] = 'Get calendar URL'; @@ -138,6 +139,7 @@ $string['pollinterval_help'] = 'How often you would like the calendar to update with new events.'; $string['preferences'] = 'Preferences'; $string['preferences_available'] = 'Your personal preferences'; +$string['preferredcalendar'] = 'Preferred calendar'; $string['pref_lookahead'] = 'Upcoming events look-ahead'; $string['pref_lookahead_help'] = 'This sets the (maximum) number of days in the future that an event has to start in in order to be displayed as an upcoming event. Events that start beyond this will never be displayed as upcoming. Please note that there is no guarantee that all events starting in this time frame will be displayed; if there are too many (more than the "Maximum upcoming events" preference) then the most distant events will not be shown.'; $string['pref_maxevents'] = 'Maximum upcoming events'; diff --git a/lang/en/calendarsystem.php b/lang/en/calendarsystem.php deleted file mode 100644 index 51b607c0a84d6..0000000000000 --- a/lang/en/calendarsystem.php +++ /dev/null @@ -1,19 +0,0 @@ - \ No newline at end of file diff --git a/lang/en/plugin.php b/lang/en/plugin.php index 630dbf64789a6..f1e79585dbf67 100644 --- a/lang/en/plugin.php +++ b/lang/en/plugin.php @@ -91,7 +91,8 @@ $string['type_cachelock_plural'] = 'Cache lock handlers'; $string['type_cachestore'] = 'Cache store'; $string['type_cachestore_plural'] = 'Cache stores'; -$string['type_calendarsystem_plural'] = 'Calendar systems'; +$string['type_calendartype'] = 'Calendar type'; +$string['type_calendartype_plural'] = 'Calendar types'; $string['type_coursereport'] = 'Course report'; $string['type_coursereport_plural'] = 'Course reports'; $string['type_editor'] = 'Editor'; diff --git a/lib/bennu/iCalendar_rfc2445.php b/lib/bennu/iCalendar_rfc2445.php index ffe4f85daff4b..d221217c61013 100644 --- a/lib/bennu/iCalendar_rfc2445.php +++ b/lib/bennu/iCalendar_rfc2445.php @@ -203,9 +203,7 @@ function rfc2445_is_valid_value($value, $type) { $m = intval(substr($value, 4, 2)); $d = intval(substr($value, 6, 2)); - // MDL-18375, Multi-Calendar Support - $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); - return $calendarsystem_gregorian->checkdate($m, $d, $y); + return checkdate($m, $d, $y); break; case RFC2445_TYPE_DATE_TIME: diff --git a/lib/classes/component.php b/lib/classes/component.php index d5ec8ac85979d..7e63b28bd6d91 100644 --- a/lib/classes/component.php +++ b/lib/classes/component.php @@ -341,6 +341,7 @@ protected static function fetch_plugintypes() { 'qtype' => $CFG->dirroot.'/question/type', 'mod' => $CFG->dirroot.'/mod', 'auth' => $CFG->dirroot.'/auth', + 'calendartype' => $CFG->dirroot.'/calendar/type', 'enrol' => $CFG->dirroot.'/enrol', 'message' => $CFG->dirroot.'/message/output', 'block' => $CFG->dirroot.'/blocks', diff --git a/lib/db/install.xml b/lib/db/install.xml index ac6eb778b6449..e26ab472a00ae 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -93,7 +93,7 @@ - + @@ -772,7 +772,7 @@ - + diff --git a/lib/form/dateselector.php b/lib/form/dateselector.php index d578e84572ea1..5e6ddea89a9dc 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -39,12 +39,10 @@ * @copyright 2007 Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class MoodleQuickForm_date_selector extends MoodleQuickForm_group -{ +class MoodleQuickForm_date_selector extends MoodleQuickForm_group { + /** - * Control the fieldnames for form elements - * - * MDL-18375, Multi-Calendar Support + * Control the fieldnames for form elements. * * startyear => int start of range of years that can be selected * stopyear => int last year that can be selected @@ -78,13 +76,11 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group * @param array $options Options to control the element's display * @param mixed $attributes Either a typical HTML attribute string or an associative array */ - function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) - { - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; - - $this->_options = array('startyear'=> $CALENDARSYSTEM->get_min_year(), 'stopyear'=>$CALENDARSYSTEM->get_max_year(), - 'timezone'=>99, 'optional'=>false); + function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { + // Get the calendar type used - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(), + 'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false); $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); $this->_persistantFreeze = true; @@ -111,18 +107,18 @@ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null * * @access private */ - function _createElements() - { - global $OUTPUT, $CALENDARSYSTEM; + function _createElements() { + global $OUTPUT; - $this->_elements = array(); - for ($i=1; $i<=31; $i++) { - $days[$i] = $i; - } - $months = $CALENDARSYSTEM->get_month_names(); - for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) { + // Get the calendar type used - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + $days = $calendartype->get_days(); + $months = $calendartype->get_months(); + for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) { $years[$i] = $i; } + + $this->_elements = array(); // E_STRICT creating elements without forms is nasty because it internally uses $this $this->_elements[] = @MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true); $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true); @@ -149,8 +145,7 @@ function _createElements() * @param object $caller calling object * @return bool */ - function onQuickFormEvent($event, $arg, &$caller) - { + function onQuickFormEvent($event, $arg, &$caller) { switch ($event) { case 'updateValue': // constant values override both default and submitted ones @@ -176,7 +171,7 @@ function onQuickFormEvent($event, $arg, &$caller) 'month' => $currentdate['mon'], 'year' => $currentdate['year']); // If optional, default to off, unless a date was provided - if($this->_options['optional']) { + if($this->_options['optional']) { $value['enabled'] = $requestvalue != 0; } } else { @@ -216,8 +211,7 @@ function onQuickFormEvent($event, $arg, &$caller) * * @return string */ - function toHtml() - { + function toHtml() { include_once('HTML/QuickForm/Renderer/Default.php'); $renderer = new HTML_QuickForm_Renderer_Default(); $renderer->setElementTemplate('{element}'); @@ -241,8 +235,7 @@ function toHtml() * @param bool $required Whether a group is required * @param string $error An error message associated with a group */ - function accept(&$renderer, $required = false, $error = null) - { + function accept(&$renderer, $required = false, $error = null) { $renderer->renderElement($this, $required, $error); } @@ -253,8 +246,7 @@ function accept(&$renderer, $required = false, $error = null) * @param bool $assoc specifies if returned array is associative * @return array */ - function exportValue(&$submitValues, $assoc = false) - { + function exportValue(&$submitValues, $assoc = false) { $value = null; $valuearray = array(); foreach ($this->_elements as $element){ @@ -271,13 +263,15 @@ function exportValue(&$submitValues, $assoc = false) return $value; } } - - $value[$this->getName()] = make_timestamp($valuearray['year'], - $valuearray['month'], - $valuearray['day'], - 0, 0, 0, - $this->_options['timezone'], - true); + // Get the calendar type used - see MDL-18375. + $calendartype = core_calendar\type_factory::factory(); + $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day']); + $value[$this->getName()] = make_timestamp($gregoriandate['year'], + $gregoriandate['month'], + $gregoriandate['day'], + 0, 0, 0, + $this->_options['timezone'], + true); return $value; } else { diff --git a/lib/form/datetimeselector.php b/lib/form/datetimeselector.php index cf4f884a49e06..40a58132d9590 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -39,11 +39,10 @@ * @copyright 2006 Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ +class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { + /** - * Options for the element - * - * MDL-18375, Multi-Calendar Support + * Options for the element. * * startyear => int start of range of years that can be selected * stopyear => int last year that can be selected @@ -79,13 +78,11 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ * @param array $options Options to control the element's display * @param mixed $attributes Either a typical HTML attribute string or an associative array */ - function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) - { - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; - - $this->_options = array('startyear'=> $CALENDARSYSTEM->get_min_year(), 'stopyear'=>$CALENDARSYSTEM->get_max_year(), - 'defaulttime' => 0, 'timezone'=>99, 'step'=>5, 'optional'=>false); + function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { + // Get the calendar type used - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(), + 'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false); $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); $this->_persistantFreeze = true; @@ -112,16 +109,14 @@ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = * * @access private */ - function _createElements() - { - global $OUTPUT, $CALENDARSYSTEM; + function _createElements() { + global $OUTPUT; - $this->_elements = array(); - for ($i=1; $i<=31; $i++) { - $days[$i] = $i; - } - $months = $CALENDARSYSTEM->get_month_names(); - for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) { + // Get the calendar type used - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + $days = $calendartype->get_days(); + $months = $calendartype->get_months(); + for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) { $years[$i] = $i; } for ($i=0; $i<=23; $i++) { @@ -130,6 +125,8 @@ function _createElements() for ($i=0; $i<60; $i+=$this->_options['step']) { $minutes[$i] = sprintf("%02d",$i); } + + $this->_elements = array(); // E_STRICT creating elements without forms is nasty because it internally uses $this $this->_elements[] = @MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true); $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true); @@ -163,8 +160,7 @@ function _createElements() * @param object $caller calling object * @return bool */ - function onQuickFormEvent($event, $arg, &$caller) - { + function onQuickFormEvent($event, $arg, &$caller) { switch ($event) { case 'updateValue': // constant values override both default and submitted ones @@ -237,8 +233,7 @@ function onQuickFormEvent($event, $arg, &$caller) * * @return string */ - function toHtml() - { + function toHtml() { include_once('HTML/QuickForm/Renderer/Default.php'); $renderer = new HTML_QuickForm_Renderer_Default(); $renderer->setElementTemplate('{element}'); @@ -262,8 +257,7 @@ function toHtml() * @param bool $required Whether a group is required * @param string $error An error message associated with a group */ - function accept(&$renderer, $required = false, $error = null) - { + function accept(&$renderer, $required = false, $error = null) { $renderer->renderElement($this, $required, $error); } @@ -274,8 +268,7 @@ function accept(&$renderer, $required = false, $error = null) * @param bool $assoc specifies if returned array is associative * @return array */ - function exportValue(&$submitValues, $assoc = false) - { + function exportValue(&$submitValues, $assoc = false) { $value = null; $valuearray = array(); foreach ($this->_elements as $element){ @@ -292,20 +285,24 @@ function exportValue(&$submitValues, $assoc = false) return $value; } } - $valuearray=$valuearray + array('year' => 1970, 'month' => 1, 'day' => 1, 'hour' => 0, 'minute' => 0); - $value[$this->getName()] = make_timestamp( - $valuearray['year'], - $valuearray['month'], - $valuearray['day'], - $valuearray['hour'], - $valuearray['minute'], - 0, - $this->_options['timezone'], - true); + // Get the calendar type used - see MDL-18375. + $calendartype = core_calendar\type_factory::factory(); + $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], + $valuearray['month'], + $valuearray['day'], + $valuearray['hour'], + $valuearray['minute']); + $value[$this->getName()] = make_timestamp($gregoriandate['year'], + $gregoriandate['month'], + $gregoriandate['day'], + $gregoriandate['hour'], + $gregoriandate['minute'], + 0, + $this->_options['timezone'], + true); return $value; } else { - return null; } } diff --git a/lib/moodlelib.php b/lib/moodlelib.php index e01f2b64780a5..3d82e23061006 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -2003,8 +2003,6 @@ function get_user_preferences($name = null, $default = null, $user = null) { /** * Given date parts in user time produce a GMT timestamp. * - * MDL-18375, Multi-Calendar Support - * * @package core * @category time * @param int $year The year part to create timestamp of @@ -2020,16 +2018,6 @@ function get_user_preferences($name = null, $default = null, $user = null) { * @return int GMT timestamp */ function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { - global $CALENDARSYSTEM; - if ($CALENDARSYSTEM->get_min_year() == 1350 && $year > 2000) { - debugging('Warning. Wrong call to make_timestamp().', DEBUG_DEVELOPER); - error('Your code must be fixed by a developer.'); - } - return $CALENDARSYSTEM->make_timestamp($year, $month, $day, $hour, $minute, $second, $timezone, $applydst); -} - -// MDL-18375, Multi-Calendar Support -function make_timestamp_old($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) { // Save input timezone, required for dst offset check. $passedtimezone = $timezone; @@ -2156,8 +2144,6 @@ function format_time($totalsecs, $str = null) { * If parameter fixday = true (default), then take off leading * zero from %d, else maintain it. * - * MDL-18375, Multi-Calendar Support - * * @package core * @category time * @param int $date the timestamp in UTC, as obtained from the database. @@ -2172,77 +2158,8 @@ function format_time($totalsecs, $str = null) { * @return string the formatted date/time. */ function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) { - global $CALENDARSYSTEM; - return $CALENDARSYSTEM->userdate($date, $format, $timezone, $fixday, $fixhour); -} - -// MDL-18375, Multi-Calendar Support -function userdate_old($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) { - - global $CFG; - - if (empty($format)) { - $format = get_string('strftimedaydatetime', 'langconfig'); - } - - if (!empty($CFG->nofixday)) { - // Config.php can force %d not to be fixed. - $fixday = false; - } else if ($fixday) { - $formatnoday = str_replace('%d', 'DD', $format); - $fixday = ($formatnoday != $format); - $format = $formatnoday; - } - - // Note: This logic about fixing 12-hour time to remove unnecessary leading - // zero is required because on Windows, PHP strftime function does not - // support the correct 'hour without leading zero' parameter (%l). - if (!empty($CFG->nofixhour)) { - // Config.php can force %I not to be fixed. - $fixhour = false; - } else if ($fixhour) { - $formatnohour = str_replace('%I', 'HH', $format); - $fixhour = ($formatnohour != $format); - $format = $formatnohour; - } - - // Add daylight saving offset for string timezones only, as we can't get dst for - // float values. if timezone is 99 (user default timezone), then try update dst. - if ((99 == $timezone) || !is_numeric($timezone)) { - $date += dst_offset_on($date, $timezone); - } - - $timezone = get_user_timezone_offset($timezone); - - // If we are running under Windows convert to windows encoding and then back to UTF-8 - // (because it's impossible to specify UTF-8 to fetch locale info in Win32). - - if (abs($timezone) > 13) { - // Server time. - $datestring = date_format_string($date, $format, $timezone); - if ($fixday) { - $daystring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %d', $date))); - $datestring = str_replace('DD', $daystring, $datestring); - } - if ($fixhour) { - $hourstring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %I', $date))); - $datestring = str_replace('HH', $hourstring, $datestring); - } - - } else { - $date += (int)($timezone * 3600); - $datestring = date_format_string($date, $format, $timezone); - if ($fixday) { - $daystring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %d', $date))); - $datestring = str_replace('DD', $daystring, $datestring); - } - if ($fixhour) { - $hourstring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %I', $date))); - $datestring = str_replace('HH', $hourstring, $datestring); - } - } - - return $datestring; + $calendartype = calendar_type_plugin_factory::factory(); + return $calendartype->userdate($date, $format, $timezone, $fixday, $fixhour); } /** @@ -2287,8 +2204,6 @@ function date_format_string($date, $format, $tz = 99) { * Given a $time timestamp in GMT (seconds since epoch), * returns an array that represents the date in user time * - * MDL-18375, Multi-Calendar Support - * * @package core * @category time * @uses HOURSECS @@ -2297,58 +2212,9 @@ function date_format_string($date, $format, $tz = 99) { * dst offset is applied {@link http://docs.moodle.org/dev/Time_API#Timezone} * @return array An array that represents the date in user time */ - function usergetdate($time, $timezone=99) { - global $CALENDARSYSTEM; - return $CALENDARSYSTEM->usergetdate($time, $timezone); -} - -// MDL-18375, Multi-Calendar Support -function usergetdate_old($time, $timezone=99) { - - // Save input timezone, required for dst offset check. - $passedtimezone = $timezone; - - $timezone = get_user_timezone_offset($timezone); - - if (abs($timezone) > 13) { - // Server time. - return getdate($time); - } - - // Add daylight saving offset for string timezones only, as we can't get dst for - // float values. if timezone is 99 (user default timezone), then try update dst. - if ($passedtimezone == 99 || !is_numeric($passedtimezone)) { - $time += dst_offset_on($time, $passedtimezone); - } - - $time += intval((float)$timezone * HOURSECS); - - $datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time); - - // Be careful to ensure the returned array matches that produced by getdate() above. - list( - $getdate['month'], - $getdate['weekday'], - $getdate['yday'], - $getdate['year'], - $getdate['mon'], - $getdate['wday'], - $getdate['mday'], - $getdate['hours'], - $getdate['minutes'], - $getdate['seconds'] - ) = explode('_', $datestring); - - // Set correct datatype to match with getdate(). - $getdate['seconds'] = (int)$getdate['seconds']; - $getdate['yday'] = (int)$getdate['yday'] - 1; // The function gmstrftime returns 0 through 365. - $getdate['year'] = (int)$getdate['year']; - $getdate['mon'] = (int)$getdate['mon']; - $getdate['wday'] = (int)$getdate['wday']; - $getdate['mday'] = (int)$getdate['mday']; - $getdate['hours'] = (int)$getdate['hours']; - $getdate['minutes'] = (int)$getdate['minutes']; - return $getdate; +function usergetdate($time, $timezone = 99) { + $calendartype = calendar_type_plugin_factory::factory(); + return $calendartype->usergetdate($time, $timezone); } /** @@ -2672,8 +2538,6 @@ function calculate_user_dst_table($fromyear = null, $toyear = null, $strtimezone /** * Calculates the required DST change and returns a Timestamp Array * - * MDL-18375, Multi-Calendar Support - * * @package core * @category time * @uses HOURSECS @@ -2695,10 +2559,8 @@ function dst_changes_for_year($year, $timezone) { list($dsthour, $dstmin) = explode(':', $timezone->dst_time); list($stdhour, $stdmin) = explode(':', $timezone->std_time); - // MDL-18375, Multi-Calendar Support - $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); - $timedst = $calendarsystem_gregorian->make_timestamp($year, $timezone->dst_month, $monthdaydst, 0, 0, 0, 99, false); - $timestd = $calendarsystem_gregorian->make_timestamp($year, $timezone->std_month, $monthdaystd, 0, 0, 0, 99, false); + $timedst = make_timestamp($year, $timezone->dst_month, $monthdaydst, 0, 0, 0, 99, false); + $timestd = make_timestamp($year, $timezone->std_month, $monthdaystd, 0, 0, 0, 99, false); // Instead of putting hour and minute in make_timestamp(), we add them afterwards. // This has the advantage of being able to have negative values for hour, i.e. for timezones @@ -2774,9 +2636,6 @@ function dst_offset_on($time, $strtimezone = null) { */ function find_day_in_month($startday, $weekday, $month, $year) { - // MDL-18375, Multi-Calendar Support - $calendarsystem_gregorian = calendarsystem_plugin_factory::factory('gregorian'); - $daysinmonth = days_in_month($month, $year); if ($weekday == -1) { @@ -2798,7 +2657,7 @@ function find_day_in_month($startday, $weekday, $month, $year) { if ($startday < 1) { $startday = abs($startday); - $lastmonthweekday = strftime('%w', $calendarsystem_gregorian->mktime(12, 0, 0, $month, $daysinmonth, $year)); + $lastmonthweekday = strftime('%w', mktime(12, 0, 0, $month, $daysinmonth, $year)); // This is the last such weekday of the month. $lastinmonth = $daysinmonth + $weekday - $lastmonthweekday; @@ -2815,7 +2674,7 @@ function find_day_in_month($startday, $weekday, $month, $year) { } else { - $indexweekday = strftime('%w', $calendarsystem_gregorian->mktime(12, 0, 0, $month, $startday, $year)); + $indexweekday = strftime('%w', mktime(12, 0, 0, $month, $startday, $year)); $diff = $weekday - $indexweekday; if ($diff < 0) { @@ -2846,8 +2705,6 @@ function days_in_month($month, $year) { /** * Calculate the position in the week of a specific calendar day * - * MDL-18375, Multi-Calendar Support - * * @package core * @category time * @param int $day The day of the date whose position in the week is sought @@ -2856,9 +2713,8 @@ function days_in_month($month, $year) { * @return int */ function dayofweek($day, $month, $year) { - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; - return $CALENDARSYSTEM->dayofweek($day, $month, $year); + // I wonder if this is any different from strftime('%w', mktime(12, 0, 0, $month, $daysinmonth, $year, 0));. + return intval(date('w', mktime(12, 0, 0, $month, $day, $year))); } // USER AUTHENTICATION AND LOGIN. diff --git a/lib/setup.php b/lib/setup.php index 27fb471b5ad60..732fbfc99b05a 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -482,13 +482,6 @@ */ global $SCRIPT; -/** - * MDL-18375, Multi-Calendar Support - * - * $CALENDARSYSTEM is a global that defines the calendar system - */ -global $CALENDARSYSTEM; - // Set httpswwwroot default value (this variable will replace $CFG->wwwroot // inside some URLs used in HTTPSPAGEREQUIRED pages. $CFG->httpswwwroot = $CFG->wwwroot; @@ -568,7 +561,7 @@ require_once($CFG->libdir .'/messagelib.php'); // Messagelib functions require_once($CFG->libdir .'/modinfolib.php'); // Cached information on course-module instances require_once($CFG->dirroot.'/cache/lib.php'); // Cache API -require_once($CFG->dirroot . '/calendarsystem/calendarsystem.class.php'); // MDL-18375, Multi-Calendar Support +require_once($CFG->dirroot.'/calendar/type/calendartype.class.php'); // Calendar type. // make sure PHP is not severly misconfigured setup_validate_php_configuration(); @@ -979,26 +972,6 @@ function stripslashes_deep($value) { } } -// MDL-18375, Multi-Calendar Support -// note: do not accept calendarsystem parameter from POST -if (isset($_GET['calendarsystem']) and ($calendarsystem = optional_param('calendarsystem', '', PARAM_SAFEDIR))) { - if (file_exists($CFG->dirroot .'/calendarsystem/'. $calendarsystem)) { - $SESSION->calendarsystem = $calendarsystem; - } -} - -unset($calendarsystem); - -if (empty($CFG->calendarsystem)) { - if (empty($SESSION->calendarsystem)) { - $CFG->calendarsystem = 'gregorian'; - } else { - $CFG->calendarsystem = $SESSION->calendarsystem; - } -} - -$CALENDARSYSTEM = calendarsystem_plugin_factory::factory(); - // note: we can not block non utf-8 installations here, because empty mysql database // might be converted to utf-8 in admin/index.php during installation diff --git a/user/editlib.php b/user/editlib.php index 9b40e635389a1..7e3abf5eca07b 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -262,9 +262,8 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager $mform->addElement('select', 'lang', get_string('preferredlanguage'), get_string_manager()->get_list_of_translations()); $mform->setDefault('lang', $CFG->lang); - // MDL-18375, Multi-Calendar Support - $mform->addElement('select', 'calendarsystem', get_string('preferredcalendar', 'calendarsystem'), get_list_of_calendars()); - $mform->setDefault('calendarsystem', $CFG->calendarsystem); + // Multi-Calendar Support - see MDL-18375. + $mform->addElement('select', 'calendartype', get_string('preferredcalendar', 'calendar'), calendar_type_plugin_factory::get_list_of_calendar_types()); if (!empty($CFG->allowuserthemes)) { $choices = array(); diff --git a/user/profile/field/datetime/define.class.php b/user/profile/field/datetime/define.class.php index 53a9ad65f6ee6..5e454925b60d4 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -16,12 +16,8 @@ class profile_define_datetime extends profile_define_base { * @param object $form the user form */ function define_form_specific($form) { - // MDL-18375, Multi-Calendar Support - global $CALENDARSYSTEM; - // Create variables to store start and end - $userdate = $CALENDARSYSTEM->usergetdate(time()); - $currentyear = $userdate['year']; + $currentyear = date('Y'); $startyear = $currentyear - 100; $endyear = $currentyear + 20; From 29cb1e83b002fffed98beda8a7734f927b8ae3ed Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Mon, 17 Jun 2013 13:20:28 +0800 Subject: [PATCH 03/16] MDL-18375 calendar: only display the YUI2 calendar when the Gregorian type is used --- lib/form/dateselector.php | 15 ++++++++++----- lib/form/datetimeselector.php | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/form/dateselector.php b/lib/form/dateselector.php index 5e6ddea89a9dc..c608e192c3796 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -98,8 +98,10 @@ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null } } } - // MDL-18375, Multi-Calendar Support - // form_init_date_js(); + // The YUI2 calendar only supports the gregorian calendar type. + if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + form_init_date_js(); + } } /** @@ -123,10 +125,13 @@ function _createElements() { $this->_elements[] = @MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true); $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true); $this->_elements[] = @MoodleQuickForm::createElement('select', 'year', get_string('year', 'form'), $years, $this->getAttributes(), true); - $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'), - array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs')); + // The YUI2 calendar only supports the gregorian calendar type so only display the calendar image if this is being used. + if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'), + array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs')); + } // If optional we add a checkbox which the user can use to turn if on - if($this->_options['optional']) { + if ($this->_options['optional']) { $this->_elements[] = @MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true); } foreach ($this->_elements as $element){ diff --git a/lib/form/datetimeselector.php b/lib/form/datetimeselector.php index 40a58132d9590..6bee569de5481 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -100,8 +100,10 @@ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = } } } - // MDL-18375, Multi-Calendar Support - // form_init_date_js(); + // The YUI2 calendar only supports the gregorian calendar type. + if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + form_init_date_js(); + } } /** @@ -138,10 +140,13 @@ function _createElements() { $this->_elements[] = @MoodleQuickForm::createElement('select', 'hour', get_string('hour', 'form'), $hours, $this->getAttributes(), true); $this->_elements[] = @MoodleQuickForm::createElement('select', 'minute', get_string('minute', 'form'), $minutes, $this->getAttributes(), true); } - $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'), - array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs')); + // The YUI2 calendar only supports the gregorian calendar type so only display the calendar image if this is being used. + if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'), + array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs')); + } // If optional we add a checkbox which the user can use to turn if on - if($this->_options['optional']) { + if ($this->_options['optional']) { $this->_elements[] = @MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true); } foreach ($this->_elements as $element){ From 7e52491cf9d4852c59f45ab355a46492bedeea9d Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Mon, 15 Jul 2013 15:40:44 +0800 Subject: [PATCH 04/16] MDL-18375 calendar: moved the location of the calendar type select box when editing a course --- course/edit_form.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/course/edit_form.php b/course/edit_form.php index ca311ef40831f..3ec565c21516a 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -199,6 +199,11 @@ function definition() { $mform->addElement('select', 'lang', get_string('forcelanguage'), $languages); $mform->setDefault('lang', $courseconfig->lang); + $calendartypes = array(); + $calendartypes[''] = get_string('forceno'); + $calendartypes += core_calendar\type_factory::get_list_of_calendar_types(); + $mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendartypes); + $options = range(0, 10); $mform->addElement('select', 'newsitems', get_string('newsitemsnumber'), $options); $mform->addHelpButton('newsitems', 'newsitemsnumber'); @@ -273,14 +278,6 @@ function definition() { $options[0] = get_string('none'); $mform->addElement('select', 'defaultgroupingid', get_string('defaultgrouping', 'group'), $options); - // Multi-Calendar Support - see MDL-18375 - $mform->addElement('header','', get_string('calendar', 'calendar')); - - $calendartypes = array(); - $calendartypes[''] = get_string('forceno'); - $calendartypes += calendar_type_plugin_factory::get_list_of_calendar_types(); - $mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendartypes); - // Customizable role names in this course. $mform->addElement('header','rolerenaming', get_string('rolerenaming')); $mform->addHelpButton('rolerenaming', 'rolerenaming'); From 62321a7ba0c1650c651bd07e2581c7e7f3cdfffa Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Mon, 1 Jul 2013 18:25:26 +0800 Subject: [PATCH 05/16] MDL-18375 calendar: edited the calendartype column in the install.xml file and created an upgrade path --- lib/db/install.xml | 4 ++-- lib/db/upgrade.php | 23 +++++++++++++++++++++++ version.php | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/db/install.xml b/lib/db/install.xml index e26ab472a00ae..f97f8364d16e9 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -93,7 +93,7 @@ - + @@ -772,7 +772,7 @@ - + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 494ec78e5253d..0fd05c32fe20c 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -2363,5 +2363,28 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2013082700.00); } + if ($oldversion < 2013090500.01) { + // Define field calendartype to be added to course. + $table = new xmldb_table('course'); + $field = new xmldb_field('calendartype', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null); + + // Conditionally launch add field calendartype. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Define field calendartype to be added to user. + $table = new xmldb_table('user'); + $field = new xmldb_field('calendartype', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'gregorian'); + + // Conditionally launch add field calendartype. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2013090500.01); + } + return true; } diff --git a/version.php b/version.php index d74c317c6f103..7273624d5d7af 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2013090500.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2013090500.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. From 84423bd9e5a37ddbbb1924b06bab7659b2d223cc Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Tue, 2 Jul 2013 18:09:45 +0800 Subject: [PATCH 06/16] MDL-18375 calendar: refactored the datetime user field so that it now uses the calendar type system --- user/profile/field/datetime/define.class.php | 103 ++++++++++++++---- user/profile/field/datetime/field.class.php | 52 ++++++--- .../lang/en/profilefield_datetime.php | 21 +++- user/profile/field/datetime/version.php | 12 +- 4 files changed, 141 insertions(+), 47 deletions(-) diff --git a/user/profile/field/datetime/define.class.php b/user/profile/field/datetime/define.class.php index 5e454925b60d4..90177d46d8403 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -1,40 +1,60 @@ . + /** - * Define datetime fields + * Define datetime fields. * - * @author Mark Nelson + * @package profilefield_datetime + * @copyright Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @version 20101022 */ class profile_define_datetime extends profile_define_base { /** - * Define the setting for a datetime custom field + * Define the setting for a datetime custom field. * - * @param object $form the user form + * @param moodleform $form the user form */ - function define_form_specific($form) { - // Create variables to store start and end - $currentyear = date('Y'); - $startyear = $currentyear - 100; - $endyear = $currentyear + 20; + public function define_form_specific($form) { + // Get the current calendar in use - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + + // Create variables to store start and end. + list($year, $month, $day) = explode('_', date('Y_m_d')); + $currentdate = $calendartype->convert_from_gregorian($year, $month, $day); + $currentyear = $currentdate['year']; + $startyear = $calendartype->get_min_year(); + $endyear = $calendartype->get_max_year(); - // Create array for the years + // Create array for the years. $arryears = array(); for ($i = $startyear; $i <= $endyear; $i++) { $arryears[$i] = $i; } - // Add elements + // Add elements. $form->addElement('select', 'param1', get_string('startyear', 'profilefield_datetime'), $arryears); $form->setType('param1', PARAM_INT); $form->setDefault('param1', $currentyear); $form->addElement('select', 'param2', get_string('endyear', 'profilefield_datetime'), $arryears); $form->setType('param2', PARAM_INT); - $form->setDefault('param2', $currentyear + 20); + $form->setDefault('param2', $currentyear); $form->addElement('checkbox', 'param3', get_string('wanttime', 'profilefield_datetime')); $form->setType('param3', PARAM_INT); @@ -44,16 +64,16 @@ function define_form_specific($form) { } /** - * Validate the data from the profile field form + * Validate the data from the profile field form. * - * @param object data from the add/edit profile field form - * @param array files - * @return array associative array of error messages + * @param stdClass $data from the add/edit profile field form + * @param array $files + * @return array associative array of error messages */ - function define_validate_specific($data, $files) { + public function define_validate_specific($data, $files) { $errors = array(); - // Make sure the start year is not greater than the end year + // Make sure the start year is not greater than the end year. if ($data->param1 > $data->param2) { $errors['param1'] = get_string('startyearafterend', 'profilefield_datetime'); } @@ -61,19 +81,54 @@ function define_validate_specific($data, $files) { return $errors; } + /** + * Alter form based on submitted or existing data. + * + * @param moodleform $mform + */ + public function define_after_data(&$mform) { + // Get the current calendar in use - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + + // The start and end year will be set as a Gregorian year in the DB. We want + // to convert these to the equivalent year in the current calendar system. + $param1 = $mform->getElement('param1'); + $year = $param1->getValue(); // The getValue() for select elements returns an array. + $year = $year[0]; + $date1 = $calendartype->convert_from_gregorian($year, 1, 1); + + $param2 = $mform->getElement('param2'); + $year = $param2->getValue(); // The getValue() for select elements returns an array. + $year = $year[0]; + $date2 = $calendartype->convert_from_gregorian($year, 1, 1); + + $param1->setValue($date1['year']); + $param2->setValue($date2['year']); + } + /** * Preprocess data from the profile field form before * it is saved. * - * @param object data from the add/edit profile field form - * @return object processed data object + * @param stdClass $data from the add/edit profile field form + * @return stdClass processed data object */ - function define_save_preprocess($data) { + public function define_save_preprocess($data) { + // Get the current calendar in use - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + + // Ensure the years are saved as Gregorian in the database. + $startdate = $calendartype->convert_to_gregorian($data->param1, 1, 1); + $stopdate = $calendartype->convert_to_gregorian($data->param2, 1, 1); + + $data->param1 = $startdate['year']; + $data->param2 = $stopdate['year']; + if (empty($data->param3)) { - $data->param3 = NULL; + $data->param3 = null; } - // No valid value in the default data column needed + // No valid value in the default data column needed. $data->defaultdata = '0'; return $data; diff --git a/user/profile/field/datetime/field.class.php b/user/profile/field/datetime/field.class.php index 17b0e3c467f1c..bde9e781169c4 100644 --- a/user/profile/field/datetime/field.class.php +++ b/user/profile/field/datetime/field.class.php @@ -1,35 +1,57 @@ . + /** - * Handles displaying and editing the datetime field + * Handles displaying and editing the datetime field. * - * @author Mark Nelson + * @package profilefield_datetime + * @copyright Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @version 20101022 */ class profile_field_datetime extends profile_field_base { /** - * Handles editing datetime fields + * Handles editing datetime fields. * - * @param object moodleform instance + * @param moodleform $mform */ - function edit_field_add($mform) { - // Check if the field is required + public function edit_field_add($mform) { + // Get the current calendar in use - see MDL-18375. + $calendartype = calendar_type_plugin_factory::factory(); + + // Check if the field is required. if ($this->field->required) { $optional = false; } else { $optional = true; } + // Convert the year stored in the DB as gregorian to that used by the calendar type. + $startdate = $calendartype->convert_from_gregorian($this->field->param1, 1, 1); + $stopdate = $calendartype->convert_from_gregorian($this->field->param2, 1, 1); + $attributes = array( - 'startyear' => $this->field->param1, - 'stopyear' => $this->field->param2, + 'startyear' => $startdate['year'], + 'stopyear' => $stopdate['year'], 'optional' => $optional ); - // Check if they wanted to include time as well + // Check if they wanted to include time as well. if (!empty($this->field->param3)) { $mform->addElement('date_time_selector', $this->inputname, format_string($this->field->name), $attributes); } else { @@ -48,7 +70,7 @@ function edit_field_add($mform) { * @return int timestamp * @since Moodle 2.5 */ - function edit_save_data_preprocess($datetime, $datarecord) { + public function edit_save_data_preprocess($datetime, $datarecord) { // If timestamp then explode it to check if year is within field limit. $isstring = strpos($datetime, '-'); if (empty($isstring)) { @@ -66,17 +88,17 @@ function edit_save_data_preprocess($datetime, $datarecord) { } /** - * Display the data for this field + * Display the data for this field. */ - function display_data() { - // Check if time was specified + public function display_data() { + // Check if time was specified. if (!empty($this->field->param3)) { $format = get_string('strftimedaydatetime', 'langconfig'); } else { $format = get_string('strftimedate', 'langconfig'); } - // Check if a date has been specified + // Check if a date has been specified. if (empty($this->data)) { return get_string('notset', 'profilefield_datetime'); } else { diff --git a/user/profile/field/datetime/lang/en/profilefield_datetime.php b/user/profile/field/datetime/lang/en/profilefield_datetime.php index 612767633f9d5..f72b898d57f16 100644 --- a/user/profile/field/datetime/lang/en/profilefield_datetime.php +++ b/user/profile/field/datetime/lang/en/profilefield_datetime.php @@ -1,11 +1,26 @@ . + /** - * The english language pack used in this profile field type + * The english language pack used in this profile field type. * - * @author Mark Nelson - Pukunui Technology + * @package profilefield_datetime + * @copyright Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @version 20101022 */ $string['currentdatedefault'] = 'Check to use current date as default'; diff --git a/user/profile/field/datetime/version.php b/user/profile/field/datetime/version.php index 1bb2ae043bb22..fa7bdb79f92c8 100644 --- a/user/profile/field/datetime/version.php +++ b/user/profile/field/datetime/version.php @@ -1,4 +1,5 @@ . /** - * @package profilefield - * @subpackage datetime - * @copyright 2010 onwards Shane Elliot {@link http://pukunui.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * Version information for the datetime field. + * + * @package profilefield_datetime + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013050100; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2013070200; // The current plugin version (Date: YYYYMMDDXX) $plugin->requires = 2013050100; // Requires this Moodle version $plugin->component = 'profilefield_datetime'; // Full name of the plugin (used for diagnostics) From 022745acd252c356e2f43a6379d9165b606e9dff Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Wed, 3 Jul 2013 17:58:14 +0800 Subject: [PATCH 07/16] MDL-18375 calendar: implemented the usage of the recently introduced automatic class loading --- .../type_base.php} | 74 +---------------- calendar/classes/type_factory.php | 81 +++++++++++++++++++ .../{lib.php => classes/structure.php} | 5 +- calendar/type/gregorian/version.php | 2 +- course/edit_form.php | 2 +- lib/form/dateselector.php | 10 +-- lib/form/datetimeselector.php | 10 +-- lib/moodlelib.php | 4 +- lib/setup.php | 1 - user/editlib.php | 2 +- user/profile/field/datetime/define.class.php | 6 +- user/profile/field/datetime/field.class.php | 2 +- 12 files changed, 107 insertions(+), 92 deletions(-) rename calendar/{type/calendartype.class.php => classes/type_base.php} (79%) create mode 100644 calendar/classes/type_factory.php rename calendar/type/gregorian/{lib.php => classes/structure.php} (97%) diff --git a/calendar/type/calendartype.class.php b/calendar/classes/type_base.php similarity index 79% rename from calendar/type/calendartype.class.php rename to calendar/classes/type_base.php index becdd6428738d..3e33efb905da1 100644 --- a/calendar/type/calendartype.class.php +++ b/calendar/classes/type_base.php @@ -15,6 +15,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +namespace core_calendar; + /** * Defines functions used by calendar type plugins. * @@ -26,7 +28,7 @@ * @copyright 2008 onwards Foodle Group {@link http://foodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class calendar_type_plugin_base { +abstract class type_base { /** * Returns a list of all the possible days for all months. @@ -232,73 +234,3 @@ function usergetdate($time, $timezone) { return $getdate; } } - -/** - * Class calendar_type_plugin_factory. - * - * Factory class producing required subclasses of {@link calendar_type_plugin_base}. - */ -class calendar_type_plugin_factory { - - /** - * Returns an instance of the currently used calendar type. - * - * @return calendar_type_plugin_* the created calendar_type class - * @throws coding_exception if the calendar type file could not be loaded - */ - static function factory() { - global $CFG; - - $type = self::get_calendar_type(); - $file = 'calendar/type/' . $type . '/lib.php'; - $fullpath = $CFG->dirroot . '/' . $file; - if (is_readable($fullpath)) { - require_once($fullpath); - $class = "calendar_type_plugin_$type"; - return new $class(); - } else { - throw new coding_exception("The calendar type file $file could not be initialised, check that it exists - and that the web server has permission to read it."); - } - } - - /** - * Returns a list of calendar typess available for use. - * - * @return array the list of calendar types - */ - static function get_list_of_calendar_types() { - $calendars = array(); - $calendardirs = core_component::get_plugin_list('calendartype'); - - foreach ($calendardirs as $name => $location) { - $calendars[$name] = get_string('name', "calendartype_{$name}"); - } - - return $calendars; - } - - /** - * Returns the current calendar type in use. - * - * @return string the current calendar type being used - */ - static function get_calendar_type() { - global $CFG, $USER, $SESSION, $COURSE; - - if (!empty($COURSE->id) and $COURSE->id != SITEID and !empty($COURSE->calendartype)) { // Course calendartype can override all other settings for this page. - $return = $COURSE->calendartype; - } else if (!empty($SESSION->calendartype)) { // Session calendartype can override other settings. - $return = $SESSION->calendartype; - } else if (!empty($USER->calendartype)) { - $return = $USER->calendartype; - } else if (!empty($CFG->calendartype)) { - $return = $CFG->calendartype; - } else { - $return = 'gregorian'; - } - - return $return; - } -} - diff --git a/calendar/classes/type_factory.php b/calendar/classes/type_factory.php new file mode 100644 index 0000000000000..96e871689a1f2 --- /dev/null +++ b/calendar/classes/type_factory.php @@ -0,0 +1,81 @@ +. + +namespace core_calendar; + +/** + * Class \core_calendar\type_factory. + * + * Factory class producing required subclasses of {@link \core_calendar\type_base}. + */ +class type_factory { + + /** + * Returns an instance of the currently used calendar type. + * + * @param string|null $type the calendar type to use, if none provided use logic to determine + * @return calendar_type_plugin_* the created calendar_type class + * @throws coding_exception if the calendar type file could not be loaded + */ + static function factory($type = null) { + if (is_null($type)) { + $type = self::get_calendar_type(); + } + + $class = "\\calendartype_$type\\structure"; + return new $class(); + } + + /** + * Returns a list of calendar typess available for use. + * + * @return array the list of calendar types + */ + static function get_list_of_calendar_types() { + $calendars = array(); + $calendardirs = \core_component::get_plugin_list('calendartype'); + + foreach ($calendardirs as $name => $location) { + $calendars[$name] = get_string('name', "calendartype_{$name}"); + } + + return $calendars; + } + + /** + * Returns the current calendar type in use. + * + * @return string the current calendar type being used + */ + static function get_calendar_type() { + global $CFG, $USER, $SESSION, $COURSE; + + if (!empty($COURSE->id) and $COURSE->id != SITEID and !empty($COURSE->calendartype)) { // Course calendartype can override all other settings for this page. + $return = $COURSE->calendartype; + } else if (!empty($SESSION->calendartype)) { // Session calendartype can override other settings. + $return = $SESSION->calendartype; + } else if (!empty($USER->calendartype)) { + $return = $USER->calendartype; + } else if (!empty($CFG->calendartype)) { + $return = $CFG->calendartype; + } else { + $return = 'gregorian'; + } + + return $return; + } +} \ No newline at end of file diff --git a/calendar/type/gregorian/lib.php b/calendar/type/gregorian/classes/structure.php similarity index 97% rename from calendar/type/gregorian/lib.php rename to calendar/type/gregorian/classes/structure.php index 3aa3143fe1354..db1bed55d7284 100644 --- a/calendar/type/gregorian/lib.php +++ b/calendar/type/gregorian/classes/structure.php @@ -15,6 +15,9 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +namespace calendartype_gregorian; +use core_calendar\type_base; + /** * Handles calendar functions for the gregorian calendar. * @@ -24,7 +27,7 @@ * @copyright 2008 onwards Foodle Group {@link http://foodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class calendar_type_plugin_gregorian extends calendar_type_plugin_base { +class structure extends type_base { /** * Returns a list of all the possible days for all months. diff --git a/calendar/type/gregorian/version.php b/calendar/type/gregorian/version.php index 5b0b203e49de6..9cd51ed1e9081 100644 --- a/calendar/type/gregorian/version.php +++ b/calendar/type/gregorian/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013062000; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2013070300; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2012120300; // Requires this Moodle version. $plugin->component = 'calendartype_gregorian'; // Full name of the plugin (used for diagnostics). diff --git a/course/edit_form.php b/course/edit_form.php index 3ec565c21516a..b04c866239b31 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -201,7 +201,7 @@ function definition() { $calendartypes = array(); $calendartypes[''] = get_string('forceno'); - $calendartypes += core_calendar\type_factory::get_list_of_calendar_types(); + $calendartypes += \core_calendar\type_factory::get_list_of_calendar_types(); $mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendartypes); $options = range(0, 10); diff --git a/lib/form/dateselector.php b/lib/form/dateselector.php index c608e192c3796..b2b17cd88d32b 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -78,7 +78,7 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { */ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { // Get the calendar type used - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(), 'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false); @@ -99,7 +99,7 @@ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null } } // The YUI2 calendar only supports the gregorian calendar type. - if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') { form_init_date_js(); } } @@ -113,7 +113,7 @@ function _createElements() { global $OUTPUT; // Get the calendar type used - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); $days = $calendartype->get_days(); $months = $calendartype->get_months(); for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) { @@ -126,7 +126,7 @@ function _createElements() { $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true); $this->_elements[] = @MoodleQuickForm::createElement('select', 'year', get_string('year', 'form'), $years, $this->getAttributes(), true); // The YUI2 calendar only supports the gregorian calendar type so only display the calendar image if this is being used. - if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') { $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'), array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs')); } @@ -269,7 +269,7 @@ function exportValue(&$submitValues, $assoc = false) { } } // Get the calendar type used - see MDL-18375. - $calendartype = core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day']); $value[$this->getName()] = make_timestamp($gregoriandate['year'], $gregoriandate['month'], diff --git a/lib/form/datetimeselector.php b/lib/form/datetimeselector.php index 6bee569de5481..90912fb845e67 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -80,7 +80,7 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { */ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { // Get the calendar type used - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(), 'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false); @@ -101,7 +101,7 @@ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = } } // The YUI2 calendar only supports the gregorian calendar type. - if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') { form_init_date_js(); } } @@ -115,7 +115,7 @@ function _createElements() { global $OUTPUT; // Get the calendar type used - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); $days = $calendartype->get_days(); $months = $calendartype->get_months(); for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) { @@ -141,7 +141,7 @@ function _createElements() { $this->_elements[] = @MoodleQuickForm::createElement('select', 'minute', get_string('minute', 'form'), $minutes, $this->getAttributes(), true); } // The YUI2 calendar only supports the gregorian calendar type so only display the calendar image if this is being used. - if (calendar_type_plugin_factory::get_calendar_type() === 'gregorian') { + if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') { $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'), array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs')); } @@ -291,7 +291,7 @@ function exportValue(&$submitValues, $assoc = false) { } } // Get the calendar type used - see MDL-18375. - $calendartype = core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day'], diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 3d82e23061006..da44e8412e5d6 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -2158,7 +2158,7 @@ function format_time($totalsecs, $str = null) { * @return string the formatted date/time. */ function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) { - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); return $calendartype->userdate($date, $format, $timezone, $fixday, $fixhour); } @@ -2213,7 +2213,7 @@ function date_format_string($date, $format, $tz = 99) { * @return array An array that represents the date in user time */ function usergetdate($time, $timezone = 99) { - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); return $calendartype->usergetdate($time, $timezone); } diff --git a/lib/setup.php b/lib/setup.php index 732fbfc99b05a..ecf4917655947 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -561,7 +561,6 @@ require_once($CFG->libdir .'/messagelib.php'); // Messagelib functions require_once($CFG->libdir .'/modinfolib.php'); // Cached information on course-module instances require_once($CFG->dirroot.'/cache/lib.php'); // Cache API -require_once($CFG->dirroot.'/calendar/type/calendartype.class.php'); // Calendar type. // make sure PHP is not severly misconfigured setup_validate_php_configuration(); diff --git a/user/editlib.php b/user/editlib.php index 7e3abf5eca07b..b008728a512e4 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -263,7 +263,7 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager $mform->setDefault('lang', $CFG->lang); // Multi-Calendar Support - see MDL-18375. - $mform->addElement('select', 'calendartype', get_string('preferredcalendar', 'calendar'), calendar_type_plugin_factory::get_list_of_calendar_types()); + $mform->addElement('select', 'calendartype', get_string('preferredcalendar', 'calendar'), \core_calendar\type_factory::get_list_of_calendar_types()); if (!empty($CFG->allowuserthemes)) { $choices = array(); diff --git a/user/profile/field/datetime/define.class.php b/user/profile/field/datetime/define.class.php index 90177d46d8403..12a4dc6188637 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -32,7 +32,7 @@ class profile_define_datetime extends profile_define_base { */ public function define_form_specific($form) { // Get the current calendar in use - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); // Create variables to store start and end. list($year, $month, $day) = explode('_', date('Y_m_d')); @@ -88,7 +88,7 @@ public function define_validate_specific($data, $files) { */ public function define_after_data(&$mform) { // Get the current calendar in use - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); // The start and end year will be set as a Gregorian year in the DB. We want // to convert these to the equivalent year in the current calendar system. @@ -115,7 +115,7 @@ public function define_after_data(&$mform) { */ public function define_save_preprocess($data) { // Get the current calendar in use - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); // Ensure the years are saved as Gregorian in the database. $startdate = $calendartype->convert_to_gregorian($data->param1, 1, 1); diff --git a/user/profile/field/datetime/field.class.php b/user/profile/field/datetime/field.class.php index bde9e781169c4..98cf81bf7e230 100644 --- a/user/profile/field/datetime/field.class.php +++ b/user/profile/field/datetime/field.class.php @@ -32,7 +32,7 @@ class profile_field_datetime extends profile_field_base { */ public function edit_field_add($mform) { // Get the current calendar in use - see MDL-18375. - $calendartype = calendar_type_plugin_factory::factory(); + $calendartype = \core_calendar\type_factory::factory(); // Check if the field is required. if ($this->field->required) { From 0ae36d6cfcdc2e63db59aed7673cd95b1f7af75a Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Wed, 10 Jul 2013 19:10:51 +0800 Subject: [PATCH 08/16] MDL-18375 calendar: created a test calendar type to use for PHPUnit tests and added tests --- calendar/tests/calendartype_test.php | 281 +++++++++++++++++++ calendar/tests/calendartype_test_example.php | 180 ++++++++++++ 2 files changed, 461 insertions(+) create mode 100644 calendar/tests/calendartype_test.php create mode 100644 calendar/tests/calendartype_test_example.php diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php new file mode 100644 index 0000000000000..66c2595ca7ff7 --- /dev/null +++ b/calendar/tests/calendartype_test.php @@ -0,0 +1,281 @@ +. + +/** + * Calendar type system unit tests. + * + * @package core_calendar + * @copyright 2013 Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +// The test calendar type. +require_once($CFG->dirroot . '/calendar/tests/calendartype_test_example.php'); + +// Used to test the dateselector elements. +require_once($CFG->libdir . '/form/dateselector.php'); +require_once($CFG->libdir . '/form/datetimeselector.php'); + +// Used to test the user datetime profile field. +require_once($CFG->dirroot . '/user/profile/lib.php'); +require_once($CFG->dirroot . '/user/profile/definelib.php'); +require_once($CFG->dirroot . '/user/profile/index_field_form.php'); + +/** + * Unit tests for the calendar type system. + * + * @package core_calendar + * @copyright 2013 Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 2.6 + */ +class core_calendar_type_testcase extends advanced_testcase { + + /** + * The test user. + */ + private $user; + + /** + * Test set up. + */ + protected function setUp() { + // The user we are going to test this on. + $this->user = self::getDataGenerator()->create_user(); + self::setUser($this->user); + } + + /** + * Test that setting the calendar type works. + */ + public function test_calendar_type_set() { + // We want to reset the test data after this run. + $this->resetAfterTest(); + + // Test setting it as the 'Test' calendar type. + $this->set_calendar_type('test'); + $this->assertEquals('test', \core_calendar\type_factory::get_calendar_type()); + + // Test setting it as the 'Gregorian' calendar type. + $this->set_calendar_type('gregorian'); + $this->assertEquals('gregorian', \core_calendar\type_factory::get_calendar_type()); + } + + /** + * Test that calling core Moodle functions responsible for displaying the date + * have the same results as directly calling the same function in the calendar type. + */ + public function test_calendar_type_core_functions() { + // We want to reset the test data after this run. + $this->resetAfterTest(); + + // Test that the core functions reproduce the same results as the Gregorian calendar. + $this->core_functions_test('gregorian'); + + // Test that the core functions reproduce the same results as the test calendar. + $this->core_functions_test('test'); + } + + /** + * Test that dates selected using the date selector elements are being saved as unixtime, and that the + * unixtime is being converted back to a valid date to display in the date selector elements for + * different calendar types. + */ + public function test_calendar_type_dateselector_elements() { + // We want to reset the test data after this run. + $this->resetAfterTest(); + + // Check converting dates to Gregorian when submitting a date selector element works. Note: the test + // calendar is 2 years, 2 months, 2 days, 2 hours and 2 minutes ahead of the Gregorian calendar. + $date1 = array(); + $date1['day'] = 4; + $date1['month'] = 7; + $date1['year'] = 2013; + $date1['hour'] = 0; + $date1['minute'] = 0; + $date1['timestamp'] = 1372896000; + $this->convert_dateselector_to_unixtime_test('dateselector', 'gregorian', $date1); + + $date2 = array(); + $date2['day'] = 7; + $date2['month'] = 9; + $date2['year'] = 2015; + $date2['hour'] = 0; // The dateselector element does not have hours. + $date2['minute'] = 0; // The dateselector element does not have minutes. + $date2['timestamp'] = 1372896000; + $this->convert_dateselector_to_unixtime_test('dateselector', 'test', $date2); + + $date3 = array(); + $date3['day'] = 4; + $date3['month'] = 7; + $date3['year'] = 2013; + $date3['hour'] = 23; + $date3['minute'] = 15; + $date3['timestamp'] = 1372979700; + $this->convert_dateselector_to_unixtime_test('datetimeselector', 'gregorian', $date3); + + $date4 = array(); + $date4['day'] = 7; + $date4['month'] = 9; + $date4['year'] = 2015; + $date4['hour'] = 1; + $date4['minute'] = 17; + $date4['timestamp'] = 1372979700; + $this->convert_dateselector_to_unixtime_test('datetimeselector', 'test', $date4); + + // The date selector element values are set by using the function usergetdate, here we want to check that + // the unixtime passed is being successfully converted to the correct values for the calendar type. + $this->convert_unixtime_to_dateselector_test('gregorian', $date3); + $this->convert_unixtime_to_dateselector_test('test', $date4); + } + + /** + * Test that the user profile field datetime minimum and maximum year settings are saved as the + * equivalent Gregorian years. + */ + public function test_calendar_type_datetime_field_submission() { + // We want to reset the test data after this run. + $this->resetAfterTest(); + + // Create an array with the input values and expected values once submitted. + $date = array(); + $date['inputminyear'] = '1970'; + $date['inputmaxyear'] = '2013'; + $date['expectedminyear'] = '1970'; + $date['expectedmaxyear'] = '2013'; + $this->datetime_field_submission_test('gregorian', $date); + + // The test calendar is 2 years, 2 months, 2 days in the future, so when the year 1970 is submitted, + // the year 1967 should be saved in the DB, as 1/1/1970 converts to 30/10/1967 in Gregorian. + $date['expectedminyear'] = '1967'; + $date['expectedmaxyear'] = '2010'; + $this->datetime_field_submission_test('test', $date); + } + + /** + * Test all the core functions that use the calendar type system. + * + * @param string $type the calendar type we want to test + */ + private function core_functions_test($type) { + $this->set_calendar_type($type); + + $class = "\\calendartype_$type\\structure"; + $calendar = new $class(); + + // Test the userdate function. + $this->assertEquals($calendar->userdate($this->user->timecreated, '', 99, true, true), userdate($this->user->timecreated)); + + // Test the usergetdate function. + $this->assertEquals($calendar->usergetdate($this->user->timecreated, '', 99, true, true), usergetdate($this->user->timecreated)); + } + + /** + * Simulates submitting a form with a date selector element and tests that the chosen dates + * are converted into unixtime before being saved in DB. + * + * @param string $element the form element we are testing + * @param string $type the calendar type we want to test + * @param array $date the date variables + */ + private function convert_dateselector_to_unixtime_test($element, $type, $date) { + $this->set_calendar_type($type); + + if ($element == 'dateselector') { + $el = new MoodleQuickForm_date_selector('dateselector', null, array('timezone' => 0.0, 'step' => 1)); + } else { + $el = new MoodleQuickForm_date_time_selector('dateselector', null, array('timezone' => 0.0, 'step' => 1)); + } + $el->_createElements(); + $submitvalues = array('dateselector' => $date); + + $this->assertSame($el->exportValue($submitvalues), array('dateselector' => $date['timestamp'])); + } + + /** + * Test converting dates from unixtime to a date for the calendar type specified. + * + * @param string $type the calendar type we want to test + * @param array $date the date variables + */ + private function convert_unixtime_to_dateselector_test($type, $date) { + $this->set_calendar_type($type); + + $usergetdate = usergetdate($date['timestamp'], 0.0); + $comparedate = array( + 'minute' => $usergetdate['minutes'], + 'hour' => $usergetdate['hours'], + 'day' => $usergetdate['mday'], + 'month' => $usergetdate['mon'], + 'year' => $usergetdate['year'], + 'timestamp' => $date['timestamp'] + ); + + $this->assertEquals($comparedate, $date); + } + + /** + * Test saving the minimum and max year settings for the user datetime field. + * + * @param string $type the calendar type we want to test + * @param array $date the date variables + */ + private function datetime_field_submission_test($type, $date) { + $this->set_calendar_type($type); + + // Get the data we are submitting for the form. + $formdata = array(); + $formdata['shortname'] = 'Shortname'; + $formdata['name'] = 'Name'; + $formdata['param1'] = $date['inputminyear']; + $formdata['param2'] = $date['inputmaxyear']; + + // Mock submitting this. + field_form::mock_submit($formdata); + + // Create the user datetime form. + $form = new field_form(null, 'datetime'); + + // Get the data from the submission. + $submissiondata = $form->get_data(); + // On the user profile field page after get_data, the function define_save is called + // in the field base class, which then calls the field's function define_save_preprocess. + $field = new profile_define_datetime(); + $submissiondata = $field->define_save_preprocess($submissiondata); + + // Create an array we want to compare with the date passed. + $comparedate = $date; + $comparedate['expectedminyear'] = $submissiondata->param1; + $comparedate['expectedmaxyear'] = $submissiondata->param2; + + $this->assertEquals($comparedate, $date); + } + + /** + * Set the calendar type for this user. + * + * @param string $type the calendar type we want to set + */ + private function set_calendar_type($type) { + $this->user->calendartype = $type; + session_set_user($this->user); + } +} diff --git a/calendar/tests/calendartype_test_example.php b/calendar/tests/calendartype_test_example.php new file mode 100644 index 0000000000000..f251ccd00600c --- /dev/null +++ b/calendar/tests/calendartype_test_example.php @@ -0,0 +1,180 @@ +. + +namespace calendartype_test; +use \core_calendar\type_base; + +/** + * Handles calendar functions for the test calendar. + * + * The test calendar is going to be 2 years, 2 days, 2 hours and 2 minutes + * in the future of the Gregorian calendar. + * + * @package core_calendar + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class structure extends type_base { + + /** + * Returns a list of all the possible days for all months. + * + * This is used to generate the select box for the days + * in the date selector elements. Some months contain more days + * than others so this function should return all possible days as + * we can not predict what month will be chosen (the user + * may have JS turned off and we need to support this situation in + * Moodle). + * + * @return array the days + */ + public function get_days() { + $days = array(); + + for ($i = 1; $i <= 31; $i++) { + $days[$i] = $i; + } + + return $days; + } + + /** + * Returns a list of all the names of the months. + * + * @return array the month names + */ + public function get_months() { + $months = array(); + + for ($i=1; $i<=12; $i++) { + $months[$i] = $i; + } + + return $months; + } + + /** + * Returns the minimum year of the calendar. + * + * @return int the minumum year + */ + public function get_min_year() { + return 1970; + } + + /** + * Returns the maximum year of the calendar. + * + * @return int the max year + */ + public function get_max_year() { + return 2050; + } + + /** + * Returns a formatted string that represents a date in user time. + * + * If parameter fixday = true (default), then take off leading + * zero from %d, else maintain it. + * + * @param int $date the timestamp in UTC, as obtained from the database. + * @param string $format strftime format. You should probably get this using + * get_string('strftime...', 'langconfig'); + * @param int|float|string $timezone by default, uses the user's time zone. if numeric and + * not 99 then daylight saving will not be added. + * {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @param bool $fixday if true (default) then the leading zero from %d is removed. + * If false then the leading zero is maintained. + * @param bool $fixhour if true (default) then the leading zero from %I is removed. + * @return string the formatted date/time. + */ + public function userdate($date, $format, $timezone, $fixday, $fixhour) { + return ""; + } + + /** + * Given a $time timestamp in GMT (seconds since epoch), returns an array that + * represents the date in user time. + * + * @param int $time Timestamp in GMT + * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no + * dst offset is applyed {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @return array An array that represents the date in user time + */ + public function usergetdate($time, $timezone) { + $date = parent::usergetdate($time, $timezone); + $newdate = $this->convert_from_gregorian($date["year"], $date["mon"], $date["mday"], + $date['hours'], $date['minutes']); + + $date["year"] = $newdate['year']; + $date["mon"] = $newdate['month']; + $date["mday"] = $newdate['day']; + $date['hours'] = $newdate['hour']; + $date['minutes'] = $newdate['minute']; + + return $date; + } + + /** + * Provided with a day, month, year, hour and minute + * convert it into the equivalent Gregorian date. + * + * @param int $year + * @param int $month + * @param int $day + * @param int $hour + * @param int $minute + * @return array the converted day, month, year, hour and minute. + */ + public function convert_to_gregorian($year, $month, $day, $hour = 0, $minute = 0) { + $timestamp = make_timestamp($year, $month, $day, $hour, $minute); + $date = date('Y/n/j/H/i', strtotime('-2 year, -2 months, -2 days, -2 hours, -2 minutes', $timestamp)); + + list($year, $month, $day, $hour, $minute) = explode('/', $date); + + return array('year' => (int) $year, + 'month' => (int) $month, + 'day' => (int) $day, + 'hour' => (int) $hour, + 'minute' => (int) $minute); + + } + + /** + * Provided with a day, month, year, hour and minute in a Gregorian date + * convert it into the specific calendar type date. + * + * @param int $year + * @param int $month + * @param int $day + * @param int $hour + * @param int $minute + * @return array the converted day, month, year, hour and minute. + */ + public function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0) { + $timestamp = make_timestamp($year, $month, $day, $hour, $minute); + $date = date('Y/n/j/H/i', strtotime('+2 year, +2 months, +2 days, +2 hours, +2 minutes', $timestamp)); + + list($year, $month, $day, $hour, $minute) = explode('/', $date); + + return array('year' => (int) $year, + 'month' => (int) $month, + 'day' => (int) $day, + 'hour' => (int) $hour, + 'minute' => (int) $minute); + } +} From f59ab4adc8259a6be3264fae753a877930733254 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Tue, 16 Jul 2013 14:22:45 +0800 Subject: [PATCH 09/16] MDL-18375 calendar: renamed the userdate/usergetdate functions and changed them to abstract Renamed the userdate/usergetdate functions in the calendar type to be more descriptive and made them abstract to ensure developers implement this functionality in their calendar type. Also tidied up PHPDocs for these functions. --- calendar/classes/type_base.php | 169 +++--------------- calendar/tests/calendartype_test.php | 6 +- calendar/tests/calendartype_test_example.php | 39 ++-- calendar/type/gregorian/classes/structure.php | 142 +++++++++++++++ lib/moodlelib.php | 31 ++-- 5 files changed, 200 insertions(+), 187 deletions(-) diff --git a/calendar/classes/type_base.php b/calendar/classes/type_base.php index 3e33efb905da1..3bd884f28d4ca 100644 --- a/calendar/classes/type_base.php +++ b/calendar/classes/type_base.php @@ -65,6 +65,32 @@ public abstract function get_min_year(); */ public abstract function get_max_year(); + /** + * Returns a formatted string that represents a date in user time. + * + * @param int $date the timestamp in UTC, as obtained from the database + * @param string $format strftime format + * @param int|float|string $timezone the timezone to use + * {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @param bool $fixday if true then the leading zero from %d is removed, + * if false then the leading zero is maintained + * @param bool $fixhour if true then the leading zero from %I is removed, + * if false then the leading zero is maintained + * @return string the formatted date/time + */ + public abstract function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour); + + /** + * Given a $time timestamp in GMT (seconds since epoch), returns an array that represents + * the date in user time. + * + * @param int $time timestamp in GMT + * @param float|int|string $timezone the timezone to use to calculate the time + * {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @return array an array that represents the date in user time + */ + public abstract function timestamp_to_date_array($time, $timezone); + /** * Provided with a day, month, year, hour and minute in the specific * calendar type convert it into the equivalent Gregorian date. @@ -90,147 +116,4 @@ public abstract function convert_to_gregorian($year, $month, $day, $hour = 0, $m * @return array the converted day, month and year. */ public abstract function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0); - - /** - * Returns a formatted string that represents a date in user time. - * - * Returns a formatted string that represents a date in user time - * WARNING: note that the format is for strftime(), not date(). - * Because of a bug in most Windows time libraries, we can't use - * the nicer %e, so we have to use %d which has leading zeroes. - * A lot of the fuss in the function is just getting rid of these leading - * zeroes as efficiently as possible. - * - * If parameter fixday = true (default), then take off leading - * zero from %d, else maintain it. - * - * @param int $date the timestamp in UTC, as obtained from the database. - * @param string $format strftime format. You should probably get this using - * get_string('strftime...', 'langconfig'); - * @param int|float|string $timezone by default, uses the user's time zone. if numeric and - * not 99 then daylight saving will not be added. - * {@link http://docs.moodle.org/dev/Time_API#Timezone} - * @param bool $fixday if true (default) then the leading zero from %d is removed. - * If false then the leading zero is maintained. - * @param bool $fixhour if true (default) then the leading zero from %I is removed. - * @return string the formatted date/time. - */ - function userdate($date, $format, $timezone, $fixday, $fixhour) { - global $CFG; - - if (empty($format)) { - $format = get_string('strftimedaydatetime', 'langconfig'); - } - - if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed. - $fixday = false; - } else if ($fixday) { - $formatnoday = str_replace('%d', 'DD', $format); - $fixday = ($formatnoday != $format); - $format = $formatnoday; - } - - // Note: This logic about fixing 12-hour time to remove unnecessary leading - // zero is required because on Windows, PHP strftime function does not - // support the correct 'hour without leading zero' parameter (%l). - if (!empty($CFG->nofixhour)) { - // Config.php can force %I not to be fixed. - $fixhour = false; - } else if ($fixhour) { - $formatnohour = str_replace('%I', 'HH', $format); - $fixhour = ($formatnohour != $format); - $format = $formatnohour; - } - - // Add daylight saving offset for string timezones only, as we can't get dst for - // float values. if timezone is 99 (user default timezone), then try update dst. - if ((99 == $timezone) || !is_numeric($timezone)) { - $date += dst_offset_on($date, $timezone); - } - - $timezone = get_user_timezone_offset($timezone); - - // If we are running under Windows convert to windows encoding and then back to UTF-8 - // (because it's impossible to specify UTF-8 to fetch locale info in Win32). - if (abs($timezone) > 13) { // Server time. - $datestring = date_format_string($date, $format, $timezone); - if ($fixday) { - $daystring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %d', $date))); - $datestring = str_replace('DD', $daystring, $datestring); - } - if ($fixhour) { - $hourstring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %I', $date))); - $datestring = str_replace('HH', $hourstring, $datestring); - } - } else { - $date += (int)($timezone * 3600); - $datestring = date_format_string($date, $format, $timezone); - if ($fixday) { - $daystring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %d', $date))); - $datestring = str_replace('DD', $daystring, $datestring); - } - if ($fixhour) { - $hourstring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %I', $date))); - $datestring = str_replace('HH', $hourstring, $datestring); - } - } - - return $datestring; - } - - /** - * Given a $time timestamp in GMT (seconds since epoch), returns an array that - * represents the date in user time. - * - * @param int $time Timestamp in GMT - * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no - * dst offset is applyed {@link http://docs.moodle.org/dev/Time_API#Timezone} - * @return array An array that represents the date in user time - */ - function usergetdate($time, $timezone) { - // Save input timezone, required for dst offset check. - $passedtimezone = $timezone; - - $timezone = get_user_timezone_offset($timezone); - - if (abs($timezone) > 13) { // Server time. - return getdate($time); - } - - // Add daylight saving offset for string timezones only, as we can't get dst for - // float values. if timezone is 99 (user default timezone), then try update dst. - if ($passedtimezone == 99 || !is_numeric($passedtimezone)) { - $time += dst_offset_on($time, $passedtimezone); - } - - $time += intval((float)$timezone * HOURSECS); - - $datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time); - - // Be careful to ensure the returned array matches that produced by getdate() above. - list ( - $getdate['month'], - $getdate['weekday'], - $getdate['yday'], - $getdate['year'], - $getdate['mon'], - $getdate['wday'], - $getdate['mday'], - $getdate['hours'], - $getdate['minutes'], - $getdate['seconds'] - ) = explode('_', $datestring); - - // Set correct datatype to match with getdate(). - $getdate['seconds'] = (int) $getdate['seconds']; - $getdate['yday'] = (int) $getdate['yday'] - 1; - $getdate['year'] = (int) $getdate['year']; - $getdate['mon'] = (int) $getdate['mon']; - $getdate['wday'] = (int) $getdate['wday']; - $getdate['mday'] = (int) $getdate['mday']; - $getdate['hours'] = (int) $getdate['hours']; - $getdate['minutes'] = (int) $getdate['minutes']; - - return $getdate; - } } diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php index 66c2595ca7ff7..146dd145f8d7e 100644 --- a/calendar/tests/calendartype_test.php +++ b/calendar/tests/calendartype_test.php @@ -182,10 +182,12 @@ private function core_functions_test($type) { $calendar = new $class(); // Test the userdate function. - $this->assertEquals($calendar->userdate($this->user->timecreated, '', 99, true, true), userdate($this->user->timecreated)); + $this->assertEquals($calendar->timestamp_to_date_string($this->user->timecreated, '', 99, true, true), + userdate($this->user->timecreated)); // Test the usergetdate function. - $this->assertEquals($calendar->usergetdate($this->user->timecreated, '', 99, true, true), usergetdate($this->user->timecreated)); + $this->assertEquals($calendar->timestamp_to_date_array($this->user->timecreated, '', 99, true, true), + usergetdate($this->user->timecreated)); } /** diff --git a/calendar/tests/calendartype_test_example.php b/calendar/tests/calendartype_test_example.php index f251ccd00600c..671cff49283de 100644 --- a/calendar/tests/calendartype_test_example.php +++ b/calendar/tests/calendartype_test_example.php @@ -88,35 +88,32 @@ public function get_max_year() { /** * Returns a formatted string that represents a date in user time. * - * If parameter fixday = true (default), then take off leading - * zero from %d, else maintain it. - * - * @param int $date the timestamp in UTC, as obtained from the database. - * @param string $format strftime format. You should probably get this using - * get_string('strftime...', 'langconfig'); - * @param int|float|string $timezone by default, uses the user's time zone. if numeric and - * not 99 then daylight saving will not be added. + * @param int $date the timestamp in UTC, as obtained from the database + * @param string $format strftime format + * @param int|float|string $timezone the timezone to use * {@link http://docs.moodle.org/dev/Time_API#Timezone} - * @param bool $fixday if true (default) then the leading zero from %d is removed. - * If false then the leading zero is maintained. - * @param bool $fixhour if true (default) then the leading zero from %I is removed. - * @return string the formatted date/time. + * @param bool $fixday if true then the leading zero from %d is removed, + * if false then the leading zero is maintained + * @param bool $fixhour if true then the leading zero from %I is removed, + * if false then the leading zero is maintained + * @return string the formatted date/time */ - public function userdate($date, $format, $timezone, $fixday, $fixhour) { + public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour) { return ""; } /** - * Given a $time timestamp in GMT (seconds since epoch), returns an array that - * represents the date in user time. + * Given a $time timestamp in GMT (seconds since epoch), returns an array that represents + * the date in user time. * - * @param int $time Timestamp in GMT - * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no - * dst offset is applyed {@link http://docs.moodle.org/dev/Time_API#Timezone} - * @return array An array that represents the date in user time + * @param int $time timestamp in GMT + * @param float|int|string $timezone the timezone to use to calculate the time + * {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @return array an array that represents the date in user time */ - public function usergetdate($time, $timezone) { - $date = parent::usergetdate($time, $timezone); + public function timestamp_to_date_array($time, $timezone) { + $gregoriancalendar = \core_calendar\type_factory::factory('gregorian'); + $date = $gregoriancalendar->timestamp_to_date_array($time, $timezone); $newdate = $this->convert_from_gregorian($date["year"], $date["mon"], $date["mday"], $date['hours'], $date['minutes']); diff --git a/calendar/type/gregorian/classes/structure.php b/calendar/type/gregorian/classes/structure.php index db1bed55d7284..04701e58df230 100644 --- a/calendar/type/gregorian/classes/structure.php +++ b/calendar/type/gregorian/classes/structure.php @@ -84,6 +84,148 @@ public function get_max_year() { return 2050; } + /** + * Returns a formatted string that represents a date in user time. + * + * Returns a formatted string that represents a date in user time + * WARNING: note that the format is for strftime(), not date(). + * Because of a bug in most Windows time libraries, we can't use + * the nicer %e, so we have to use %d which has leading zeroes. + * A lot of the fuss in the function is just getting rid of these leading + * zeroes as efficiently as possible. + * + * If parameter fixday = true (default), then take off leading + * zero from %d, else maintain it. + * + * @param int $date the timestamp in UTC, as obtained from the database + * @param string $format strftime format + * @param int|float|string $timezone the timezone to use + * {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @param bool $fixday if true then the leading zero from %d is removed, + * if false then the leading zero is maintained + * @param bool $fixhour if true then the leading zero from %I is removed, + * if false then the leading zero is maintained + * @return string the formatted date/time + */ + public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour) { + global $CFG; + + if (empty($format)) { + $format = get_string('strftimedaydatetime', 'langconfig'); + } + + if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed. + $fixday = false; + } else if ($fixday) { + $formatnoday = str_replace('%d', 'DD', $format); + $fixday = ($formatnoday != $format); + $format = $formatnoday; + } + + // Note: This logic about fixing 12-hour time to remove unnecessary leading + // zero is required because on Windows, PHP strftime function does not + // support the correct 'hour without leading zero' parameter (%l). + if (!empty($CFG->nofixhour)) { + // Config.php can force %I not to be fixed. + $fixhour = false; + } else if ($fixhour) { + $formatnohour = str_replace('%I', 'HH', $format); + $fixhour = ($formatnohour != $format); + $format = $formatnohour; + } + + // Add daylight saving offset for string timezones only, as we can't get dst for + // float values. if timezone is 99 (user default timezone), then try update dst. + if ((99 == $timezone) || !is_numeric($timezone)) { + $date += dst_offset_on($date, $timezone); + } + + $timezone = get_user_timezone_offset($timezone); + + // If we are running under Windows convert to windows encoding and then back to UTF-8 + // (because it's impossible to specify UTF-8 to fetch locale info in Win32). + if (abs($timezone) > 13) { // Server time. + $datestring = date_format_string($date, $format, $timezone); + if ($fixday) { + $daystring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %d', $date))); + $datestring = str_replace('DD', $daystring, $datestring); + } + if ($fixhour) { + $hourstring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %I', $date))); + $datestring = str_replace('HH', $hourstring, $datestring); + } + } else { + $date += (int)($timezone * 3600); + $datestring = date_format_string($date, $format, $timezone); + if ($fixday) { + $daystring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %d', $date))); + $datestring = str_replace('DD', $daystring, $datestring); + } + if ($fixhour) { + $hourstring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %I', $date))); + $datestring = str_replace('HH', $hourstring, $datestring); + } + } + + return $datestring; + } + + /** + * Given a $time timestamp in GMT (seconds since epoch), returns an array that + * represents the date in user time. + * + * @param int $time Timestamp in GMT + * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no + * dst offset is applied {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @return array an array that represents the date in user time + */ + public function timestamp_to_date_array($time, $timezone) { + // Save input timezone, required for dst offset check. + $passedtimezone = $timezone; + + $timezone = get_user_timezone_offset($timezone); + + if (abs($timezone) > 13) { // Server time. + return getdate($time); + } + + // Add daylight saving offset for string timezones only, as we can't get dst for + // float values. if timezone is 99 (user default timezone), then try update dst. + if ($passedtimezone == 99 || !is_numeric($passedtimezone)) { + $time += dst_offset_on($time, $passedtimezone); + } + + $time += intval((float)$timezone * HOURSECS); + + $datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time); + + // Be careful to ensure the returned array matches that produced by getdate() above. + list ( + $getdate['month'], + $getdate['weekday'], + $getdate['yday'], + $getdate['year'], + $getdate['mon'], + $getdate['wday'], + $getdate['mday'], + $getdate['hours'], + $getdate['minutes'], + $getdate['seconds'] + ) = explode('_', $datestring); + + // Set correct datatype to match with getdate(). + $getdate['seconds'] = (int) $getdate['seconds']; + $getdate['yday'] = (int) $getdate['yday'] - 1; + $getdate['year'] = (int) $getdate['year']; + $getdate['mon'] = (int) $getdate['mon']; + $getdate['wday'] = (int) $getdate['wday']; + $getdate['mday'] = (int) $getdate['mday']; + $getdate['hours'] = (int) $getdate['hours']; + $getdate['minutes'] = (int) $getdate['minutes']; + + return $getdate; + } + /** * Provided with a day, month, year, hour and minute in a specific * calendar type convert it into the equivalent Gregorian date. diff --git a/lib/moodlelib.php b/lib/moodlelib.php index da44e8412e5d6..ff34aac4ef947 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -2132,24 +2132,14 @@ function format_time($totalsecs, $str = null) { } /** - * Returns a formatted string that represents a date in user time - * - * Returns a formatted string that represents a date in user time - * WARNING: note that the format is for strftime(), not date(). - * Because of a bug in most Windows time libraries, we can't use - * the nicer %e, so we have to use %d which has leading zeroes. - * A lot of the fuss in the function is just getting rid of these leading - * zeroes as efficiently as possible. - * - * If parameter fixday = true (default), then take off leading - * zero from %d, else maintain it. + * Returns a formatted string that represents a date in user time. * * @package core * @category time * @param int $date the timestamp in UTC, as obtained from the database. * @param string $format strftime format. You should probably get this using * get_string('strftime...', 'langconfig'); - * @param int|float|string $timezone by default, uses the user's time zone. if numeric and + * @param int|float|string $timezone by default, uses the user's time zone. if numeric and * not 99 then daylight saving will not be added. * {@link http://docs.moodle.org/dev/Time_API#Timezone} * @param bool $fixday If true (default) then the leading zero from %d is removed. @@ -2159,7 +2149,7 @@ function format_time($totalsecs, $str = null) { */ function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) { $calendartype = \core_calendar\type_factory::factory(); - return $calendartype->userdate($date, $format, $timezone, $fixday, $fixhour); + return $calendartype->timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour); } /** @@ -2201,20 +2191,19 @@ function date_format_string($date, $format, $tz = 99) { } /** - * Given a $time timestamp in GMT (seconds since epoch), - * returns an array that represents the date in user time + * Given a $time timestamp in GMT (seconds since epoch), returns an array that represents + * the date in user time. * * @package core * @category time - * @uses HOURSECS - * @param int $time Timestamp in GMT - * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no - * dst offset is applied {@link http://docs.moodle.org/dev/Time_API#Timezone} - * @return array An array that represents the date in user time + * @param int $time timestamp in GMT + * @param float|int|string $timezone the timezone to use to calculate the time + * {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @return array an array that represents the date in user time */ function usergetdate($time, $timezone = 99) { $calendartype = \core_calendar\type_factory::factory(); - return $calendartype->usergetdate($time, $timezone); + return $calendartype->timestamp_to_date_array($time, $timezone); } /** From df01e4c748d04c92fb6269c6a22922376956ffbe Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Wed, 14 Aug 2013 16:02:33 +0800 Subject: [PATCH 10/16] MDL-18375 calendar: PHPDoc tidy up as well as some other minor changes --- calendar/classes/type_base.php | 3 --- calendar/classes/type_factory.php | 15 +++++++++------ calendar/tests/calendartype_test.php | 3 +-- calendar/tests/calendartype_test_example.php | 15 +++++++-------- calendar/type/gregorian/classes/structure.php | 5 +---- .../gregorian/lang/en/calendartype_gregorian.php | 5 ++--- calendar/type/gregorian/version.php | 2 +- user/profile/field/datetime/define.class.php | 4 +--- user/profile/field/datetime/field.class.php | 4 +--- .../datetime/lang/en/profilefield_datetime.php | 3 +-- user/profile/field/datetime/version.php | 3 +-- 11 files changed, 25 insertions(+), 37 deletions(-) diff --git a/calendar/classes/type_base.php b/calendar/classes/type_base.php index 3bd884f28d4ca..6458220d80f85 100644 --- a/calendar/classes/type_base.php +++ b/calendar/classes/type_base.php @@ -1,5 +1,4 @@ - * @author Mark Nelson * @copyright 2008 onwards Foodle Group {@link http://foodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/classes/type_factory.php b/calendar/classes/type_factory.php index 96e871689a1f2..b87deaae0d106 100644 --- a/calendar/classes/type_factory.php +++ b/calendar/classes/type_factory.php @@ -1,5 +1,4 @@ id) and $COURSE->id != SITEID and !empty($COURSE->calendartype)) { // Course calendartype can override all other settings for this page. @@ -78,4 +81,4 @@ static function get_calendar_type() { return $return; } -} \ No newline at end of file +} diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php index 146dd145f8d7e..e5c8ca1620049 100644 --- a/calendar/tests/calendartype_test.php +++ b/calendar/tests/calendartype_test.php @@ -1,5 +1,4 @@ . /** - * Calendar type system unit tests. + * This file contains the class that handles testing the calendar type system. * * @package core_calendar * @copyright 2013 Mark Nelson diff --git a/calendar/tests/calendartype_test_example.php b/calendar/tests/calendartype_test_example.php index 671cff49283de..8cc2f785c8ec9 100644 --- a/calendar/tests/calendartype_test_example.php +++ b/calendar/tests/calendartype_test_example.php @@ -1,5 +1,4 @@ + * @copyright 2013 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class structure extends type_base { @@ -60,7 +59,7 @@ public function get_days() { public function get_months() { $months = array(); - for ($i=1; $i<=12; $i++) { + for ($i = 1; $i <= 12; $i++) { $months[$i] = $i; } @@ -99,7 +98,7 @@ public function get_max_year() { * @return string the formatted date/time */ public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour) { - return ""; + return ''; } /** @@ -114,12 +113,12 @@ public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fi public function timestamp_to_date_array($time, $timezone) { $gregoriancalendar = \core_calendar\type_factory::factory('gregorian'); $date = $gregoriancalendar->timestamp_to_date_array($time, $timezone); - $newdate = $this->convert_from_gregorian($date["year"], $date["mon"], $date["mday"], + $newdate = $this->convert_from_gregorian($date['year'], $date['mon'], $date['mday'], $date['hours'], $date['minutes']); - $date["year"] = $newdate['year']; - $date["mon"] = $newdate['month']; - $date["mday"] = $newdate['day']; + $date['year'] = $newdate['year']; + $date['mon'] = $newdate['month']; + $date['mday'] = $newdate['day']; $date['hours'] = $newdate['hour']; $date['minutes'] = $newdate['minute']; diff --git a/calendar/type/gregorian/classes/structure.php b/calendar/type/gregorian/classes/structure.php index 04701e58df230..7a7527fcf0818 100644 --- a/calendar/type/gregorian/classes/structure.php +++ b/calendar/type/gregorian/classes/structure.php @@ -1,5 +1,4 @@ - * @author Mark Nelson + * @package calendartype_gregorian * @copyright 2008 onwards Foodle Group {@link http://foodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/type/gregorian/lang/en/calendartype_gregorian.php b/calendar/type/gregorian/lang/en/calendartype_gregorian.php index d6d8625746e26..9d2c5ba452906 100644 --- a/calendar/type/gregorian/lang/en/calendartype_gregorian.php +++ b/calendar/type/gregorian/lang/en/calendartype_gregorian.php @@ -1,5 +1,4 @@ . /** - * Strings for component 'calendar_type_plugin_gregorian', language 'en'. + * Strings for component 'calendartype_gregorian', language 'en'. * - * @package calendar_type_plugin_gregorian + * @package calendartype_gregorian * @copyright 2008 onwards Foodle Group {@link http://foodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/type/gregorian/version.php b/calendar/type/gregorian/version.php index 9cd51ed1e9081..40dce15d93ee9 100644 --- a/calendar/type/gregorian/version.php +++ b/calendar/type/gregorian/version.php @@ -17,7 +17,7 @@ /** * Version details. * - * @package calendar_type_plugin_gregorian + * @package calendartype_gregorian * @copyright 2008 onwards Foodle Group {@link http://foodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/user/profile/field/datetime/define.class.php b/user/profile/field/datetime/define.class.php index 12a4dc6188637..e0d1bbe8f435c 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -1,5 +1,4 @@ + * @copyright 2010 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ - class profile_define_datetime extends profile_define_base { /** diff --git a/user/profile/field/datetime/field.class.php b/user/profile/field/datetime/field.class.php index 98cf81bf7e230..6342b6ca56d9e 100644 --- a/user/profile/field/datetime/field.class.php +++ b/user/profile/field/datetime/field.class.php @@ -1,5 +1,4 @@ + * @copyright 2010 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ - class profile_field_datetime extends profile_field_base { /** diff --git a/user/profile/field/datetime/lang/en/profilefield_datetime.php b/user/profile/field/datetime/lang/en/profilefield_datetime.php index f72b898d57f16..53ec7de4c9ea8 100644 --- a/user/profile/field/datetime/lang/en/profilefield_datetime.php +++ b/user/profile/field/datetime/lang/en/profilefield_datetime.php @@ -1,5 +1,4 @@ + * @copyright 2010 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ diff --git a/user/profile/field/datetime/version.php b/user/profile/field/datetime/version.php index fa7bdb79f92c8..dd2e9277dfc6b 100644 --- a/user/profile/field/datetime/version.php +++ b/user/profile/field/datetime/version.php @@ -1,5 +1,4 @@ + * @copyright 2010 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ From df5d27d8927d98d6fe7d8f9587155dcae845e9ee Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Wed, 14 Aug 2013 16:48:23 +0800 Subject: [PATCH 11/16] MDL-18375 calendar: only display the choice of calendar types if there is more than one --- course/edit_form.php | 13 +++++++++---- user/editlib.php | 6 +++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/course/edit_form.php b/course/edit_form.php index b04c866239b31..fff5e6a3be33b 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -199,10 +199,15 @@ function definition() { $mform->addElement('select', 'lang', get_string('forcelanguage'), $languages); $mform->setDefault('lang', $courseconfig->lang); - $calendartypes = array(); - $calendartypes[''] = get_string('forceno'); - $calendartypes += \core_calendar\type_factory::get_list_of_calendar_types(); - $mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendartypes); + // Multi-Calendar Support - see MDL-18375. + $calendartypes = \core_calendar\type_factory::get_list_of_calendar_types(); + // We do not want to show this option unless there is more than one calendar type to display. + if (count($calendartypes) > 1) { + $calendars = array(); + $calendars[''] = get_string('forceno'); + $calendars += $calendartypes; + $mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendars); + } $options = range(0, 10); $mform->addElement('select', 'newsitems', get_string('newsitemsnumber'), $options); diff --git a/user/editlib.php b/user/editlib.php index b008728a512e4..32a4634532f55 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -263,7 +263,11 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager $mform->setDefault('lang', $CFG->lang); // Multi-Calendar Support - see MDL-18375. - $mform->addElement('select', 'calendartype', get_string('preferredcalendar', 'calendar'), \core_calendar\type_factory::get_list_of_calendar_types()); + $calendartypes = \core_calendar\type_factory::get_list_of_calendar_types(); + // We do not want to show this option unless there is more than one calendar type to display. + if (count($calendartypes) > 1) { + $mform->addElement('select', 'calendartype', get_string('preferredcalendar', 'calendar'), $calendartypes); + } if (!empty($CFG->allowuserthemes)) { $choices = array(); From 5989677e0f83e453d767c0960280fde4ad314e76 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Wed, 14 Aug 2013 17:36:42 +0800 Subject: [PATCH 12/16] MDL-18375 calendar: added the Gregorian calendar type to the standard list of plugins --- lib/pluginlib.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/pluginlib.php b/lib/pluginlib.php index 5df2fe1c435b4..cc8ae89267678 100644 --- a/lib/pluginlib.php +++ b/lib/pluginlib.php @@ -652,6 +652,7 @@ public static function is_deleted_standard_plugin($type, $name) { * @return false|array array of standard plugins or false if the type is unknown */ public static function standard_plugins_list($type) { + $standard_plugins = array( 'assignment' => array( @@ -704,6 +705,10 @@ public static function standard_plugins_list($type) { 'file', 'memcache', 'memcached', 'mongodb', 'session', 'static' ), + 'calendartype' => array( + 'gregorian' + ), + 'coursereport' => array( //deprecated! ), From 2aefba53a5f04c80169f96cf8d44167c2578bf0e Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Thu, 15 Aug 2013 16:39:22 +0800 Subject: [PATCH 13/16] MDL-18375 calendar: added condition to ensure calendar type exists before loading --- calendar/classes/type_factory.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/calendar/classes/type_factory.php b/calendar/classes/type_factory.php index b87deaae0d106..42df077b2f68e 100644 --- a/calendar/classes/type_factory.php +++ b/calendar/classes/type_factory.php @@ -40,6 +40,13 @@ public static function factory($type = null) { } $class = "\\calendartype_$type\\structure"; + + // Ensure the calendar type exists. It may occur that a user has selected a calendar type, which was then + // deleted. If this happens we want to fall back on the Gregorian calendar type. + if (!class_exists($class)) { + $class = "\\calendartype_gregorian\\structure"; + } + return new $class(); } From 6eafa4ddbafc96e1112a6881576dcd7867b65b0e Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Tue, 20 Aug 2013 16:32:40 +0800 Subject: [PATCH 14/16] MDL-18375 calendar: changed the name of the function factory to be more descriptive --- calendar/classes/type_factory.php | 2 +- calendar/tests/calendartype_test_example.php | 2 +- lib/form/dateselector.php | 6 +++--- lib/form/datetimeselector.php | 6 +++--- lib/moodlelib.php | 4 ++-- user/profile/field/datetime/define.class.php | 6 +++--- user/profile/field/datetime/field.class.php | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/calendar/classes/type_factory.php b/calendar/classes/type_factory.php index 42df077b2f68e..535dd2bbb0298 100644 --- a/calendar/classes/type_factory.php +++ b/calendar/classes/type_factory.php @@ -34,7 +34,7 @@ class type_factory { * @return calendartype_* the created calendar_type class * @throws coding_exception if the calendar type file could not be loaded */ - public static function factory($type = null) { + public static function get_calendar_instance($type = null) { if (is_null($type)) { $type = self::get_calendar_type(); } diff --git a/calendar/tests/calendartype_test_example.php b/calendar/tests/calendartype_test_example.php index 8cc2f785c8ec9..679422e925658 100644 --- a/calendar/tests/calendartype_test_example.php +++ b/calendar/tests/calendartype_test_example.php @@ -111,7 +111,7 @@ public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fi * @return array an array that represents the date in user time */ public function timestamp_to_date_array($time, $timezone) { - $gregoriancalendar = \core_calendar\type_factory::factory('gregorian'); + $gregoriancalendar = \core_calendar\type_factory::get_calendar_instance('gregorian'); $date = $gregoriancalendar->timestamp_to_date_array($time, $timezone); $newdate = $this->convert_from_gregorian($date['year'], $date['mon'], $date['mday'], $date['hours'], $date['minutes']); diff --git a/lib/form/dateselector.php b/lib/form/dateselector.php index b2b17cd88d32b..7fa61e4e46c5e 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -78,7 +78,7 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { */ function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { // Get the calendar type used - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(), 'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false); @@ -113,7 +113,7 @@ function _createElements() { global $OUTPUT; // Get the calendar type used - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); $days = $calendartype->get_days(); $months = $calendartype->get_months(); for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) { @@ -269,7 +269,7 @@ function exportValue(&$submitValues, $assoc = false) { } } // Get the calendar type used - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day']); $value[$this->getName()] = make_timestamp($gregoriandate['year'], $gregoriandate['month'], diff --git a/lib/form/datetimeselector.php b/lib/form/datetimeselector.php index 90912fb845e67..21bc4588a2d07 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -80,7 +80,7 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { */ function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) { // Get the calendar type used - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(), 'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false); @@ -115,7 +115,7 @@ function _createElements() { global $OUTPUT; // Get the calendar type used - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); $days = $calendartype->get_days(); $months = $calendartype->get_months(); for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) { @@ -291,7 +291,7 @@ function exportValue(&$submitValues, $assoc = false) { } } // Get the calendar type used - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day'], diff --git a/lib/moodlelib.php b/lib/moodlelib.php index ff34aac4ef947..4992f4f0101d8 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -2148,7 +2148,7 @@ function format_time($totalsecs, $str = null) { * @return string the formatted date/time. */ function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) { - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); return $calendartype->timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour); } @@ -2202,7 +2202,7 @@ function date_format_string($date, $format, $tz = 99) { * @return array an array that represents the date in user time */ function usergetdate($time, $timezone = 99) { - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); return $calendartype->timestamp_to_date_array($time, $timezone); } diff --git a/user/profile/field/datetime/define.class.php b/user/profile/field/datetime/define.class.php index e0d1bbe8f435c..619a74d4d998a 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -30,7 +30,7 @@ class profile_define_datetime extends profile_define_base { */ public function define_form_specific($form) { // Get the current calendar in use - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); // Create variables to store start and end. list($year, $month, $day) = explode('_', date('Y_m_d')); @@ -86,7 +86,7 @@ public function define_validate_specific($data, $files) { */ public function define_after_data(&$mform) { // Get the current calendar in use - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); // The start and end year will be set as a Gregorian year in the DB. We want // to convert these to the equivalent year in the current calendar system. @@ -113,7 +113,7 @@ public function define_after_data(&$mform) { */ public function define_save_preprocess($data) { // Get the current calendar in use - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); // Ensure the years are saved as Gregorian in the database. $startdate = $calendartype->convert_to_gregorian($data->param1, 1, 1); diff --git a/user/profile/field/datetime/field.class.php b/user/profile/field/datetime/field.class.php index 6342b6ca56d9e..cbf506bdec2e7 100644 --- a/user/profile/field/datetime/field.class.php +++ b/user/profile/field/datetime/field.class.php @@ -30,7 +30,7 @@ class profile_field_datetime extends profile_field_base { */ public function edit_field_add($mform) { // Get the current calendar in use - see MDL-18375. - $calendartype = \core_calendar\type_factory::factory(); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); // Check if the field is required. if ($this->field->required) { From deed22ea39a4a0634f620def7965aa9898f2d162 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Fri, 23 Aug 2013 14:14:50 +0800 Subject: [PATCH 15/16] MDL-18375 calendar: removed usage of the calendar type in the usergetdate function The usergetdate function is not only used to display dates, it is also passed to the function make_timestamp. This means users using another calendar type other than Gregorian will generate incorrect timestamps which may be saved in the DB or used to populate the date_selector and date_time_selector elements. For example, when creating an assignment using another calendar type other than Gregorian, the mod_form.php file calls $this->apply_admin_defaults() which uses the function usergetmidnight to set the "Allow submissions from" date to today's date and the "Due date" field to 7 days in the future. The usergetmidnight function calls usergetdate which is then passed to make_timestamp. Since the usergetdate function was using the calendar type's timestamp_to_date_array function the date being passed to make_timestamp was not in Gregorian. So, when using the hijri calendar the year 1434 was being passed which was generating a large negative number as the timestamp which was then used to populate the date fields. --- calendar/tests/calendartype_test.php | 13 ++-- calendar/type/gregorian/classes/structure.php | 45 +------------- calendar/type/gregorian/version.php | 2 +- lib/form/dateselector.php | 17 ++--- lib/form/datetimeselector.php | 19 +++--- lib/moodlelib.php | 62 ++++++++++++++++--- 6 files changed, 80 insertions(+), 78 deletions(-) diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php index e5c8ca1620049..7c80251fb360f 100644 --- a/calendar/tests/calendartype_test.php +++ b/calendar/tests/calendartype_test.php @@ -177,16 +177,12 @@ public function test_calendar_type_datetime_field_submission() { private function core_functions_test($type) { $this->set_calendar_type($type); - $class = "\\calendartype_$type\\structure"; - $calendar = new $class(); + // Get the calendar. + $calendar = \core_calendar\type_factory::get_calendar_instance(); // Test the userdate function. $this->assertEquals($calendar->timestamp_to_date_string($this->user->timecreated, '', 99, true, true), userdate($this->user->timecreated)); - - // Test the usergetdate function. - $this->assertEquals($calendar->timestamp_to_date_array($this->user->timecreated, '', 99, true, true), - usergetdate($this->user->timecreated)); } /** @@ -220,7 +216,10 @@ private function convert_dateselector_to_unixtime_test($element, $type, $date) { private function convert_unixtime_to_dateselector_test($type, $date) { $this->set_calendar_type($type); - $usergetdate = usergetdate($date['timestamp'], 0.0); + // Get the calendar. + $calendar = \core_calendar\type_factory::get_calendar_instance(); + + $usergetdate = $calendar->timestamp_to_date_array($date['timestamp'], 0.0); $comparedate = array( 'minute' => $usergetdate['minutes'], 'hour' => $usergetdate['hours'], diff --git a/calendar/type/gregorian/classes/structure.php b/calendar/type/gregorian/classes/structure.php index 7a7527fcf0818..d209864d299f8 100644 --- a/calendar/type/gregorian/classes/structure.php +++ b/calendar/type/gregorian/classes/structure.php @@ -177,50 +177,7 @@ public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fi * @return array an array that represents the date in user time */ public function timestamp_to_date_array($time, $timezone) { - // Save input timezone, required for dst offset check. - $passedtimezone = $timezone; - - $timezone = get_user_timezone_offset($timezone); - - if (abs($timezone) > 13) { // Server time. - return getdate($time); - } - - // Add daylight saving offset for string timezones only, as we can't get dst for - // float values. if timezone is 99 (user default timezone), then try update dst. - if ($passedtimezone == 99 || !is_numeric($passedtimezone)) { - $time += dst_offset_on($time, $passedtimezone); - } - - $time += intval((float)$timezone * HOURSECS); - - $datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time); - - // Be careful to ensure the returned array matches that produced by getdate() above. - list ( - $getdate['month'], - $getdate['weekday'], - $getdate['yday'], - $getdate['year'], - $getdate['mon'], - $getdate['wday'], - $getdate['mday'], - $getdate['hours'], - $getdate['minutes'], - $getdate['seconds'] - ) = explode('_', $datestring); - - // Set correct datatype to match with getdate(). - $getdate['seconds'] = (int) $getdate['seconds']; - $getdate['yday'] = (int) $getdate['yday'] - 1; - $getdate['year'] = (int) $getdate['year']; - $getdate['mon'] = (int) $getdate['mon']; - $getdate['wday'] = (int) $getdate['wday']; - $getdate['mday'] = (int) $getdate['mday']; - $getdate['hours'] = (int) $getdate['hours']; - $getdate['minutes'] = (int) $getdate['minutes']; - - return $getdate; + return usergetdate($time, $timezone); } /** diff --git a/calendar/type/gregorian/version.php b/calendar/type/gregorian/version.php index 40dce15d93ee9..deeac17ed5eaa 100644 --- a/calendar/type/gregorian/version.php +++ b/calendar/type/gregorian/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013070300; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2013082300; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2012120300; // Requires this Moodle version. $plugin->component = 'calendartype_gregorian'; // Full name of the plugin (used for diagnostics). diff --git a/lib/form/dateselector.php b/lib/form/dateselector.php index 7fa61e4e46c5e..4e94b09360d55 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -153,12 +153,12 @@ function _createElements() { function onQuickFormEvent($event, $arg, &$caller) { switch ($event) { case 'updateValue': - // constant values override both default and submitted ones - // default values are overriden by submitted + // Constant values override both default and submitted ones + // default values are overriden by submitted. $value = $this->_findValue($caller->_constantValues); 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 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()) { $value = $this->_findValue($caller->_submitValues); } else { @@ -170,19 +170,20 @@ function onQuickFormEvent($event, $arg, &$caller) { $value = time(); } if (!is_array($value)) { - $currentdate = usergetdate($value, $this->_options['timezone']); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); + $currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']); $value = array( 'day' => $currentdate['mday'], 'month' => $currentdate['mon'], 'year' => $currentdate['year']); - // If optional, default to off, unless a date was provided - if($this->_options['optional']) { + // If optional, default to off, unless a date was provided. + if ($this->_options['optional']) { $value['enabled'] = $requestvalue != 0; } } else { $value['enabled'] = isset($value['enabled']); } - if (null !== $value){ + if (null !== $value) { $this->setValue($value); } break; diff --git a/lib/form/datetimeselector.php b/lib/form/datetimeselector.php index 21bc4588a2d07..e3a908ec3df91 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -168,12 +168,12 @@ function _createElements() { function onQuickFormEvent($event, $arg, &$caller) { switch ($event) { case 'updateValue': - // constant values override both default and submitted ones - // default values are overriden by submitted + // Constant values override both default and submitted ones + // default values are overriden by submitted. $value = $this->_findValue($caller->_constantValues); 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 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()) { $value = $this->_findValue($caller->_submitValues); } else { @@ -188,7 +188,8 @@ function onQuickFormEvent($event, $arg, &$caller) { } } if (!is_array($value)) { - $currentdate = usergetdate($value, $this->_options['timezone']); + $calendartype = \core_calendar\type_factory::get_calendar_instance(); + $currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']); // Round minutes to the previous multiple of step. $currentdate['minutes'] -= $currentdate['minutes'] % $this->_options['step']; $value = array( @@ -197,19 +198,19 @@ function onQuickFormEvent($event, $arg, &$caller) { 'day' => $currentdate['mday'], 'month' => $currentdate['mon'], 'year' => $currentdate['year']); - // If optional, default to off, unless a date was provided - if($this->_options['optional']) { + // If optional, default to off, unless a date was provided. + if ($this->_options['optional']) { $value['enabled'] = $requestvalue != 0; } } else { $value['enabled'] = isset($value['enabled']); } - if (null !== $value){ + if (null !== $value) { $this->setValue($value); } break; case 'createElement': - if($arg[2]['optional']) { + if ($arg[2]['optional']) { // When using the function addElement, rather than createElement, we still // enter this case, making this check necessary. if ($this->_usedcreateelement) { diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 4992f4f0101d8..ff068d4a46c86 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -2191,19 +2191,63 @@ function date_format_string($date, $format, $tz = 99) { } /** - * Given a $time timestamp in GMT (seconds since epoch), returns an array that represents - * the date in user time. + * Given a $time timestamp in GMT (seconds since epoch), + * returns an array that represents the date in user time * * @package core * @category time - * @param int $time timestamp in GMT - * @param float|int|string $timezone the timezone to use to calculate the time - * {@link http://docs.moodle.org/dev/Time_API#Timezone} - * @return array an array that represents the date in user time + * @uses HOURSECS + * @param int $time Timestamp in GMT + * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no + * dst offset is applied {@link http://docs.moodle.org/dev/Time_API#Timezone} + * @return array An array that represents the date in user time */ -function usergetdate($time, $timezone = 99) { - $calendartype = \core_calendar\type_factory::get_calendar_instance(); - return $calendartype->timestamp_to_date_array($time, $timezone); +function usergetdate($time, $timezone=99) { + + // Save input timezone, required for dst offset check. + $passedtimezone = $timezone; + + $timezone = get_user_timezone_offset($timezone); + + if (abs($timezone) > 13) { + // Server time. + return getdate($time); + } + + // Add daylight saving offset for string timezones only, as we can't get dst for + // float values. if timezone is 99 (user default timezone), then try update dst. + if ($passedtimezone == 99 || !is_numeric($passedtimezone)) { + $time += dst_offset_on($time, $passedtimezone); + } + + $time += intval((float)$timezone * HOURSECS); + + $datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time); + + // Be careful to ensure the returned array matches that produced by getdate() above. + list( + $getdate['month'], + $getdate['weekday'], + $getdate['yday'], + $getdate['year'], + $getdate['mon'], + $getdate['wday'], + $getdate['mday'], + $getdate['hours'], + $getdate['minutes'], + $getdate['seconds'] + ) = explode('_', $datestring); + + // Set correct datatype to match with getdate(). + $getdate['seconds'] = (int)$getdate['seconds']; + $getdate['yday'] = (int)$getdate['yday'] - 1; // The function gmstrftime returns 0 through 365. + $getdate['year'] = (int)$getdate['year']; + $getdate['mon'] = (int)$getdate['mon']; + $getdate['wday'] = (int)$getdate['wday']; + $getdate['mday'] = (int)$getdate['mday']; + $getdate['hours'] = (int)$getdate['hours']; + $getdate['minutes'] = (int)$getdate['minutes']; + return $getdate; } /** From 5ca04d0ef1d8f39673f0aa25814666f4479f7c69 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Sun, 25 Aug 2013 17:38:16 +0800 Subject: [PATCH 16/16] MDL-18375 calendar: fixed issue when resaving the year in the datetime field causing the year to decrease For example, a user may create a date/time profile field and set the 'Start year' field to '2012'. Another user, using the Hijri calendar, may edit the name of this field. They visit the settings page and in this case the date '1/1/2012' is converted to '7/2/1433' in Hijri. So, the year '1433' is then displayed. The user then changes the name of this field and saves the form. This is where the issue occurs, as the date '1/1/1433' is converted into Gregorian, which converts to the year '26/09/2011', so the year '2011' is saved in the DB, not '2012'. --- calendar/tests/calendartype_test.php | 1 + user/profile/field/datetime/define.class.php | 76 +++++++++++++++----- user/profile/field/datetime/version.php | 2 +- 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php index 7c80251fb360f..10e72ea254fff 100644 --- a/calendar/tests/calendartype_test.php +++ b/calendar/tests/calendartype_test.php @@ -243,6 +243,7 @@ private function datetime_field_submission_test($type, $date) { // Get the data we are submitting for the form. $formdata = array(); + $formdata['id'] = 0; $formdata['shortname'] = 'Shortname'; $formdata['name'] = 'Name'; $formdata['param1'] = $date['inputminyear']; diff --git a/user/profile/field/datetime/define.class.php b/user/profile/field/datetime/define.class.php index 619a74d4d998a..dfeb3e1d089fe 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -57,6 +57,18 @@ public function define_form_specific($form) { $form->addElement('checkbox', 'param3', get_string('wanttime', 'profilefield_datetime')); $form->setType('param3', PARAM_INT); + $form->addElement('hidden', 'startday', '1'); + $form->setType('startday', PARAM_INT); + $form->addElement('hidden', 'startmonth', '1'); + $form->setType('startmonth', PARAM_INT); + $form->addElement('hidden', 'startyear', '1'); + $form->setType('startyear', PARAM_INT); + $form->addElement('hidden', 'endday', '1'); + $form->setType('endday', PARAM_INT); + $form->addElement('hidden', 'endmonth', '1'); + $form->setType('endmonth', PARAM_INT); + $form->addElement('hidden', 'endyear', '1'); + $form->setType('endyear', PARAM_INT); $form->addElement('hidden', 'defaultdata', '0'); $form->setType('defaultdata', PARAM_INT); } @@ -85,23 +97,45 @@ public function define_validate_specific($data, $files) { * @param moodleform $mform */ public function define_after_data(&$mform) { + global $DB; + + // If we are adding a new profile field then the dates have already been set + // by setDefault to the correct dates in the used calendar system. We only want + // to execute the rest of the code when we have the years in the DB saved in + // Gregorian that need converting to the date for this user. + $id = required_param('id', PARAM_INT); + if ($id === 0) { + return; + } + + // Get the field data from the DB. + $field = $DB->get_record('user_info_field', array('id' => $id), 'param1, param2', MUST_EXIST); + // Get the current calendar in use - see MDL-18375. $calendartype = \core_calendar\type_factory::get_calendar_instance(); + // An array to store form values. + $values = array(); + // The start and end year will be set as a Gregorian year in the DB. We want - // to convert these to the equivalent year in the current calendar system. - $param1 = $mform->getElement('param1'); - $year = $param1->getValue(); // The getValue() for select elements returns an array. - $year = $year[0]; - $date1 = $calendartype->convert_from_gregorian($year, 1, 1); - - $param2 = $mform->getElement('param2'); - $year = $param2->getValue(); // The getValue() for select elements returns an array. - $year = $year[0]; - $date2 = $calendartype->convert_from_gregorian($year, 1, 1); - - $param1->setValue($date1['year']); - $param2->setValue($date2['year']); + // convert these to the equivalent year in the current calendar type being used. + $startdate = $calendartype->convert_from_gregorian($field->param1, 1, 1); + $values['startday'] = $startdate['day']; + $values['startmonth'] = $startdate['month']; + $values['startyear'] = $startdate['year']; + $values['param1'] = $startdate['year']; + + $stopdate = $calendartype->convert_from_gregorian($field->param2, 1, 1); + $values['endday'] = $stopdate['day']; + $values['endmonth'] = $stopdate['month']; + $values['endyear'] = $stopdate['year']; + $values['param2'] = $stopdate['year']; + + // Set the values. + foreach ($values as $key => $value) { + $param = $mform->getElement($key); + $param->setValue($value); + } } /** @@ -115,9 +149,19 @@ public function define_save_preprocess($data) { // Get the current calendar in use - see MDL-18375. $calendartype = \core_calendar\type_factory::get_calendar_instance(); - // Ensure the years are saved as Gregorian in the database. - $startdate = $calendartype->convert_to_gregorian($data->param1, 1, 1); - $stopdate = $calendartype->convert_to_gregorian($data->param2, 1, 1); + // Check if the start year was changed, if it was then convert from the start of that year. + if ($data->param1 != $data->startyear) { + $startdate = $calendartype->convert_to_gregorian($data->param1, 1, 1); + } else { + $startdate = $calendartype->convert_to_gregorian($data->param1, $data->startmonth, $data->startday); + } + + // Check if the end year was changed, if it was then convert from the start of that year. + if ($data->param2 != $data->endyear) { + $stopdate = $calendartype->convert_to_gregorian($data->param2, 1, 1); + } else { + $stopdate = $calendartype->convert_to_gregorian($data->param2, $data->endmonth, $data->endday); + } $data->param1 = $startdate['year']; $data->param2 = $stopdate['year']; diff --git a/user/profile/field/datetime/version.php b/user/profile/field/datetime/version.php index dd2e9277dfc6b..9567c5e542d26 100644 --- a/user/profile/field/datetime/version.php +++ b/user/profile/field/datetime/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013070200; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2013090200; // The current plugin version (Date: YYYYMMDDXX) $plugin->requires = 2013050100; // Requires this Moodle version $plugin->component = 'profilefield_datetime'; // Full name of the plugin (used for diagnostics)