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 1ee3a7ad2c4..b5293df9ab5 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -45,6 +45,8 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page 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 502d5e667ad..4587d3412ee 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -454,6 +454,13 @@ if ($hassiteconfig) { } } +// 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 7949d94eada..d2144139cca 100644 --- a/admin/tool/uploaduser/index.php +++ b/admin/tool/uploaduser/index.php @@ -81,8 +81,10 @@ $stryesnooptions = array(0=>$strno, 1=>$stryes); $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 abe28089e9e..11e816264a9 100644 --- a/blocks/calendar_month/block_calendar_month.php +++ b/blocks/calendar_month/block_calendar_month.php @@ -10,7 +10,7 @@ class block_calendar_month extends block_base { } 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 @@ class block_calendar_month extends block_base { $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 027527bf9dc..71717a8e151 100644 --- a/calendar/event.php +++ b/calendar/event.php @@ -133,9 +133,10 @@ if ($eventid !== 0) { 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 7cd585bdcf0..f5e638a65f6 100644 --- a/calendar/export_execute.php +++ b/calendar/export_execute.php @@ -34,7 +34,9 @@ if (!$authuserid && !$authusername) { $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 @@ if(!empty($what) && !empty($time)) { $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 ede82803316..20f5a8f28e1 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 4fc9a05d76c..1e05d89b463 100644 --- a/calendar/renderer.php +++ b/calendar/renderer.php @@ -380,6 +380,8 @@ class core_calendar_renderer extends plugin_renderer_base { */ 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 @@ class core_calendar_renderer extends plugin_renderer_base { $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 40a2d82a135..8995f6d3950 100644 --- a/calendar/view.php +++ b/calendar/view.php @@ -88,7 +88,8 @@ $pagetitle = ''; $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 00000000000..f32981a6d1c --- /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 00000000000..cea0f3839db --- /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 00000000000..bfe48052420 --- /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 00000000000..c0df03a3f48 --- /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 00000000000..2cb6e5f6aed --- /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 00000000000..ae024527913 --- /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 00000000000..54ea267cf6a --- /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 00000000000..04f02d017fd --- /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 00000000000..233d14979a2 --- /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 00000000000..64024e6739a --- /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 00000000000..839795664be --- /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 00000000000..dd5e435398d --- /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 00000000000..64a7a86cef1 --- /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 00000000000..35d662c7c9f --- /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 00000000000..bb397749d64 --- /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 00000000000..cc6b69da3c9 --- /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 00000000000..24c4d6d02a4 --- /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 06f74359cfc..983a7e0fb75 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -271,6 +271,13 @@ class course_edit_form extends moodleform { $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 c1a6f80c9b3..6fcdb8dd1f8 100644 --- a/enrol/manual/ajax.php +++ b/enrol/manual/ajax.php @@ -113,8 +113,10 @@ switch ($action) { 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 10e12e1e4b0..03b2a9883c1 100644 --- a/enrol/manual/lib.php +++ b/enrol/manual/lib.php @@ -230,8 +230,10 @@ class enrol_manual_plugin extends enrol_plugin { 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 7d91e4b6017..96ac9de6650 100644 --- a/enrol/manual/manage.php +++ b/enrol/manual/manage.php @@ -92,8 +92,11 @@ if ($extendperiod) { // 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 00000000000..51b607c0a84 --- /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 e65e1ea7f18..630dbf64789 100644 --- a/lang/en/plugin.php +++ b/lang/en/plugin.php @@ -91,6 +91,7 @@ $string['type_cachelock'] = 'Cache lock handler'; $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 d221217c610..ffe4f85daff 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 cb6b59793e6..ac6eb778b64 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 f4cb2c5bcfd..d578e84572e 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group } } } - form_init_date_js(); + // MDL-18375, Multi-Calendar Support + // form_init_date_js(); } /** @@ -103,15 +113,13 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group */ 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 0bc6a7730c5..cf4f884a49e 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -42,6 +42,9 @@ require_once($CFG->libdir . '/formslib.php'); 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ } } } - form_init_date_js(); + // MDL-18375, Multi-Calendar Support + // form_init_date_js(); } /** @@ -104,15 +114,13 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ */ 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 a0fae10295d..e01f2b64780 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 ecf49176559..27fb471b5ad 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -482,6 +482,13 @@ global $FULLSCRIPT; */ 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 .'/editorlib.php'); // All text editor related f 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 @@ if (isset($CFG->maintenance_later) and $CFG->maintenance_later <= time()) { } } +// 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 42489b19a04..9b40e635389 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 5e454925b60..53a9ad65f6e 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 b5293df9ab5..1ee3a7ad2c4 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -45,8 +45,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page 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 4587d3412ee..502d5e667ad 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -454,13 +454,6 @@ if ($hassiteconfig) { } } -// 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 d2144139cca..7949d94eada 100644 --- a/admin/tool/uploaduser/index.php +++ b/admin/tool/uploaduser/index.php @@ -81,10 +81,8 @@ $stryesnooptions = array(0=>$strno, 1=>$stryes); $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 11e816264a9..abe28089e9e 100644 --- a/blocks/calendar_month/block_calendar_month.php +++ b/blocks/calendar_month/block_calendar_month.php @@ -10,7 +10,7 @@ class block_calendar_month extends block_base { } 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 @@ class block_calendar_month extends block_base { $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 71717a8e151..027527bf9dc 100644 --- a/calendar/event.php +++ b/calendar/event.php @@ -133,10 +133,9 @@ if ($eventid !== 0) { 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 f5e638a65f6..7cd585bdcf0 100644 --- a/calendar/export_execute.php +++ b/calendar/export_execute.php @@ -34,9 +34,7 @@ if (!$authuserid && !$authusername) { $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 @@ if(!empty($what) && !empty($time)) { $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 20f5a8f28e1..ede82803316 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 1e05d89b463..4fc9a05d76c 100644 --- a/calendar/renderer.php +++ b/calendar/renderer.php @@ -380,8 +380,6 @@ class core_calendar_renderer extends plugin_renderer_base { */ 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 @@ class core_calendar_renderer extends plugin_renderer_base { $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 00000000000..becdd642873 --- /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 24c4d6d02a4..d6d8625746e 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 00000000000..3aa3143fe13 --- /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 64024e6739a..5b0b203e49d 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 8995f6d3950..40a2d82a135 100644 --- a/calendar/view.php +++ b/calendar/view.php @@ -88,8 +88,7 @@ $pagetitle = ''; $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 f32981a6d1c..00000000000 --- 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 cea0f3839db..00000000000 --- 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 bfe48052420..00000000000 --- 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 c0df03a3f48..00000000000 --- 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 2cb6e5f6aed..00000000000 --- 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 ae024527913..00000000000 --- 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 54ea267cf6a..00000000000 --- 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 04f02d017fd..00000000000 --- 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 233d14979a2..00000000000 --- 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 839795664be..00000000000 --- 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 dd5e435398d..00000000000 --- 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 64a7a86cef1..00000000000 --- 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 35d662c7c9f..00000000000 --- 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 bb397749d64..00000000000 --- 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 cc6b69da3c9..00000000000 --- 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 983a7e0fb75..ca311ef4083 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -6,12 +6,18 @@ require_once($CFG->libdir.'/formslib.php'); 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 @@ class course_edit_form extends moodleform { $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 @@ class course_edit_form extends moodleform { $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 @@ class course_edit_form extends moodleform { $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 @@ class course_edit_form extends moodleform { } } -//-------------------------------------------------------------------------------- $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 @@ class course_edit_form extends moodleform { } } -/// 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 6fcdb8dd1f8..c1a6f80c9b3 100644 --- a/enrol/manual/ajax.php +++ b/enrol/manual/ajax.php @@ -113,10 +113,8 @@ switch ($action) { 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 03b2a9883c1..10e12e1e4b0 100644 --- a/enrol/manual/lib.php +++ b/enrol/manual/lib.php @@ -230,10 +230,8 @@ class enrol_manual_plugin extends enrol_plugin { 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 96ac9de6650..7d91e4b6017 100644 --- a/enrol/manual/manage.php +++ b/enrol/manual/manage.php @@ -92,11 +92,8 @@ if ($extendperiod) { // 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 d230f6755c1..ef68ec963b6 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -570,8 +570,9 @@ $string['gradeexport'] = 'Primary grade export methods'; $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 75d51b9dcb6..7a6a6aff494 100644 --- a/lang/en/calendar.php +++ b/lang/en/calendar.php @@ -93,6 +93,7 @@ $string['export'] = 'Export'; $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'] = 'Update interval'; $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 51b607c0a84..00000000000 --- 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 630dbf64789..f1e79585dbf 100644 --- a/lang/en/plugin.php +++ b/lang/en/plugin.php @@ -91,7 +91,8 @@ $string['type_cachelock'] = 'Cache lock handler'; $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 ffe4f85daff..d221217c610 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 d5ec8ac8597..7e63b28bd6d 100644 --- a/lib/classes/component.php +++ b/lib/classes/component.php @@ -341,6 +341,7 @@ $cache = '.var_export($cache, true).'; '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 ac6eb778b64..e26ab472a00 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 d578e84572e..5e6ddea89a9 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -39,12 +39,10 @@ require_once($CFG->libdir . '/formslib.php'); * @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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group * * @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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group * @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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group '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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group * * @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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group * @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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group * @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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group 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 cf4f884a49e..40a58132d95 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -39,11 +39,10 @@ require_once($CFG->libdir . '/formslib.php'); * @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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ * * @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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ * @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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ * * @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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ * @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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ * @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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{ 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 e01f2b64780..3d82e230610 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 27fb471b5ad..732fbfc99b0 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -482,13 +482,6 @@ global $FULLSCRIPT; */ 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 .'/editorlib.php'); // All text editor related f 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 @@ if (isset($CFG->maintenance_later) and $CFG->maintenance_later <= time()) { } } -// 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 9b40e635389..7e3abf5eca0 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 53a9ad65f6e..5e454925b60 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 5e6ddea89a9..c608e192c37 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -98,8 +98,10 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { } } } - // 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { $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 40a58132d95..6bee569de54 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -100,8 +100,10 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { } } } - // 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { $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 ca311ef4083..3ec565c2151 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -199,6 +199,11 @@ class course_edit_form extends moodleform { $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 @@ class course_edit_form extends moodleform { $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 e26ab472a00..f97f8364d16 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 494ec78e525..0fd05c32fe2 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 d74c317c6f1..7273624d5d7 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 5e454925b60..90177d46d84 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 array for the years + // 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. $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 @@ class profile_define_datetime extends profile_define_base { } /** - * 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 @@ class profile_define_datetime extends profile_define_base { 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 17b0e3c467f..bde9e781169 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 @@ class profile_field_datetime extends profile_field_base { * @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 @@ class profile_field_datetime extends profile_field_base { } /** - * 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 612767633f9..f72b898d57f 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 1bb2ae043bb..fa7bdb79f92 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 becdd642873..3e33efb905d 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 @@ abstract class calendar_type_plugin_base { 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 00000000000..96e871689a1 --- /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 3aa3143fe13..db1bed55d72 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 5b0b203e49d..9cd51ed1e90 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 3ec565c2151..b04c866239b 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -201,7 +201,7 @@ class course_edit_form extends moodleform { $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 c608e192c37..b2b17cd88d3 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { } } // 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { $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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { } } // 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 6bee569de54..90912fb845e 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { } } // 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { $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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { } } // 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 3d82e230610..da44e8412e5 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 732fbfc99b0..ecf49176559 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -561,7 +561,6 @@ require_once($CFG->libdir .'/editorlib.php'); // All text editor related f 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 7e3abf5eca0..b008728a512 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 90177d46d84..12a4dc61886 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 @@ class profile_define_datetime extends profile_define_base { */ 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 @@ class profile_define_datetime extends profile_define_base { */ 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 bde9e781169..98cf81bf7e2 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 00000000000..66c2595ca7f --- /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 00000000000..f251ccd0060 --- /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 3e33efb905d..3bd884f28d4 100644 --- a/calendar/classes/type_base.php +++ b/calendar/classes/type_base.php @@ -65,6 +65,32 @@ abstract class type_base { */ 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 @@ abstract class type_base { * @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 66c2595ca7f..146dd145f8d 100644 --- a/calendar/tests/calendartype_test.php +++ b/calendar/tests/calendartype_test.php @@ -182,10 +182,12 @@ class core_calendar_type_testcase extends advanced_testcase { $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 f251ccd0060..671cff49283 100644 --- a/calendar/tests/calendartype_test_example.php +++ b/calendar/tests/calendartype_test_example.php @@ -88,35 +88,32 @@ class structure extends type_base { /** * 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 db1bed55d72..04701e58df2 100644 --- a/calendar/type/gregorian/classes/structure.php +++ b/calendar/type/gregorian/classes/structure.php @@ -84,6 +84,148 @@ class structure extends type_base { 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 da44e8412e5..ff34aac4ef9 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 3bd884f28d4..6458220d80f 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 96e871689a1..b87deaae0d1 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 @@ class type_factory { return $return; } -} \ No newline at end of file +} diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php index 146dd145f8d..e5c8ca16200 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 671cff49283..8cc2f785c8e 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 @@ class structure extends type_base { 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 @@ class structure extends type_base { * @return string the formatted date/time */ public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour) { - return ""; + return ''; } /** @@ -114,12 +113,12 @@ class structure extends type_base { 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 04701e58df2..7a7527fcf08 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 d6d8625746e..9d2c5ba4529 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 9cd51ed1e90..40dce15d93e 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 12a4dc61886..e0d1bbe8f43 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 98cf81bf7e2..6342b6ca56d 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 f72b898d57f..53ec7de4c9e 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 fa7bdb79f92..dd2e9277dfc 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 b04c866239b..fff5e6a3be3 100644 --- a/course/edit_form.php +++ b/course/edit_form.php @@ -199,10 +199,15 @@ class course_edit_form extends moodleform { $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 b008728a512..32a4634532f 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 5df2fe1c435..cc8ae892676 100644 --- a/lib/pluginlib.php +++ b/lib/pluginlib.php @@ -652,6 +652,7 @@ class plugin_manager { * @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 @@ class plugin_manager { '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 b87deaae0d1..42df077b2f6 100644 --- a/calendar/classes/type_factory.php +++ b/calendar/classes/type_factory.php @@ -40,6 +40,13 @@ class type_factory { } $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 42df077b2f6..535dd2bbb02 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 8cc2f785c8e..679422e9256 100644 --- a/calendar/tests/calendartype_test_example.php +++ b/calendar/tests/calendartype_test_example.php @@ -111,7 +111,7 @@ class structure extends type_base { * @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 b2b17cd88d3..7fa61e4e46c 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { } } // 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 90912fb845e..21bc4588a2d 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { } } // 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 ff34aac4ef9..4992f4f0101 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 e0d1bbe8f43..619a74d4d99 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 @@ class profile_define_datetime extends profile_define_base { */ 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 @@ class profile_define_datetime extends profile_define_base { */ 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 6342b6ca56d..cbf506bdec2 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 e5c8ca16200..7c80251fb36 100644 --- a/calendar/tests/calendartype_test.php +++ b/calendar/tests/calendartype_test.php @@ -177,16 +177,12 @@ class core_calendar_type_testcase extends advanced_testcase { 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 @@ class core_calendar_type_testcase extends advanced_testcase { 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 7a7527fcf08..d209864d299 100644 --- a/calendar/type/gregorian/classes/structure.php +++ b/calendar/type/gregorian/classes/structure.php @@ -177,50 +177,7 @@ class structure extends type_base { * @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 40dce15d93e..deeac17ed5e 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 7fa61e4e46c..4e94b09360d 100644 --- a/lib/form/dateselector.php +++ b/lib/form/dateselector.php @@ -153,12 +153,12 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { 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 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group { $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 21bc4588a2d..e3a908ec3df 100644 --- a/lib/form/datetimeselector.php +++ b/lib/form/datetimeselector.php @@ -168,12 +168,12 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { } } 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 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group { '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 4992f4f0101..ff068d4a46c 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 | 72 ++++++++++++++++---- user/profile/field/datetime/version.php | 2 +- 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php index 7c80251fb36..10e72ea254f 100644 --- a/calendar/tests/calendartype_test.php +++ b/calendar/tests/calendartype_test.php @@ -243,6 +243,7 @@ class core_calendar_type_testcase extends advanced_testcase { // 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 619a74d4d99..dfeb3e1d089 100644 --- a/user/profile/field/datetime/define.class.php +++ b/user/profile/field/datetime/define.class.php @@ -57,6 +57,18 @@ class profile_define_datetime extends profile_define_base { $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 @@ class profile_define_datetime extends profile_define_base { * @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); + // 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']; - $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); + $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']; - $param1->setValue($date1['year']); - $param2->setValue($date2['year']); + // Set the values. + foreach ($values as $key => $value) { + $param = $mform->getElement($key); + $param->setValue($value); + } } /** @@ -115,9 +149,19 @@ class profile_define_datetime extends profile_define_base { // 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 dd2e9277dfc..9567c5e542d 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)