MDL-18375 calendar: added multiple calendar support
authorShamim Rezaie <support@foodle.org>
Mon, 10 Jun 2013 04:47:43 +0000 (12:47 +0800)
committerMark Nelson <markn@moodle.com>
Thu, 5 Sep 2013 10:30:05 +0000 (18:30 +0800)
Conflicts:

course/edit_form.php
lib/db/install.xml
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/setup.php

40 files changed:
admin/settings/appearance.php
admin/settings/plugins.php
admin/tool/uploaduser/index.php
blocks/calendar_month/block_calendar_month.php
calendar/event.php
calendar/export_execute.php
calendar/lib.php
calendar/renderer.php
calendar/view.php
calendarsystem/admin.php [new file with mode: 0644]
calendarsystem/calendarsystem.class.php [new file with mode: 0644]
calendarsystem/gregorian/calendarsystem.php [new file with mode: 0644]
calendarsystem/gregorian/lang/en/calendarsystem_gregorian.php [new file with mode: 0644]
calendarsystem/gregorian/lang/fa/calendarsystem_gregorian.php [new file with mode: 0644]
calendarsystem/gregorian/version.php [new file with mode: 0644]
calendarsystem/hijri/calendarsystem.php [new file with mode: 0644]
calendarsystem/hijri/lang/en/calendarsystem_hijri.php [new file with mode: 0644]
calendarsystem/hijri/lang/fa/calendarsystem_hijri.php [new file with mode: 0644]
calendarsystem/hijri/version.php [new file with mode: 0644]
calendarsystem/index.php [new file with mode: 0644]
calendarsystem/jalali/calendarsystem.php [new file with mode: 0644]
calendarsystem/jalali/lang/en/calendarsystem_jalali.php [new file with mode: 0644]
calendarsystem/jalali/lang/fa/calendarsystem_jalali.php [new file with mode: 0644]
calendarsystem/jalali/version.php [new file with mode: 0644]
calendarsystem/updatechecker.php [new file with mode: 0644]
calendarsystem/version.php [new file with mode: 0644]
course/edit_form.php
enrol/manual/ajax.php
enrol/manual/lib.php
enrol/manual/manage.php
lang/en/calendarsystem.php [new file with mode: 0644]
lang/en/plugin.php
lib/bennu/iCalendar_rfc2445.php
lib/db/install.xml
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/moodlelib.php
lib/setup.php
user/editlib.php
user/profile/field/datetime/define.class.php

index 1ee3a7a..b5293df 100644 (file)
@@ -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'),
index 502d5e6..4587d34 100644 (file)
@@ -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')));
index 7949d94..d214413 100644 (file)
@@ -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',
index abe2808..11e8162 100644 (file)
@@ -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 .= '<div class="filters calendar_filters">'.calendar_filter_controls($this->page->url).'</div>';
         }
 
+        // 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('<span style="font-weight: normal;">'.get_string('system', 'calendarsystem').'</span>');
+
+            $this->content->text .= '
+            <div id="changecalendarlink" style="display: none; visibility: hidden;">
+                <a style="font-weight: normal;" onclick="return toggleCalendarVisibility(document.getElementById(\'choosecalendar\'))" href="#">
+                ' . get_string('changecalendar', 'calendarsystem') . '
+                </a>
+            </div>
+            ' . $OUTPUT->render($calendarselect) . '
+            <script language="JavaScript">
+                function toggleCalendarVisibility (choosecalendar) {
+                    if (choosecalendar.style.visibility != "visible") {
+                        choosecalendar.style.display = "block";
+                        choosecalendar.style.visibility = "visible";
+                    } else {
+                        choosecalendar.style.display = "none";
+                        choosecalendar.style.visibility = "hidden";
+                    }
+
+                    return false;
+                }
+
+                document.getElementById ( "choosecalendar" ).style.display = "none";
+                document.getElementById ( "choosecalendar" ).style.visibility = "hidden";
+
+                document.getElementById ( "changecalendarlink" ).style.display = "inline";
+                document.getElementById ( "changecalendarlink" ).style.visibility = "visible";
+            </script>
+             ';
+        }
+
         return $this->content;
     }
 }
index 027527b..71717a8 100644 (file)
@@ -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);
index 7cd585b..f5e638a 100644 (file)
@@ -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
index ede8280..20f5a8f 100644 (file)
@@ -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 = '&amp;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);
 }
index 4fc9a05..1e05d89 100644 (file)
@@ -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()
         }
 
index 40a2d82..8995f6d 100644 (file)
@@ -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 (file)
index 0000000..f32981a
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+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 (file)
index 0000000..cea0f38
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+abstract class calendarsystem_plugin_base
+{
+       public abstract function calendar_days_in_month($m, $y);
+       public abstract function usergetdate($time, $timezone=99);
+       public abstract function checkdate($m, $d, $y);
+       public abstract function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true);
+       public abstract function userdate($date, $format='', $timezone=99, $fixday = true, $fixhour = true);
+       public abstract function today();
+       public abstract function get_month_names();
+       public abstract function get_min_year();
+       public abstract function get_max_year();
+       public abstract function gmmktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null);
+       public abstract function mktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null);
+       public abstract function dayofweek($day, $month, $year);
+}
+
+/**
+* calendarsystem_plugin_factory is used to "manufacture" an instance of required calendar system.
+*/
+
+class calendarsystem_plugin_factory {
+    static function factory($system = '') {
+        global $CFG;
+        if (!$system) {
+            $system = current_calendarsystem_plugin();
+            // empty($CFG->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 (file)
index 0000000..bfe4805
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+
+class calendarsystem_plugin_gregorian extends calendarsystem_plugin_base
+{
+       public function calendar_days_in_month($m, $y)
+       {
+           return intval(date('t', mktime(0, 0, 0, $m, 1, $y)));
+       }
+
+       public function usergetdate($time, $timezone=99) {
+               return usergetdate_old($time, $timezone);
+       }
+
+       public function checkdate($m, $d, $y)
+       {
+               return checkdate($m, $d, $y);
+       }
+
+       public function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) {
+               return make_timestamp_old($year, $month, $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_gregorian');
+            $pmstring = get_string('pm', 'calendarsystem_gregorian');
+            $AMstring = get_string('am_caps', 'calendarsystem_gregorian');
+            $PMstring = get_string('pm_caps', 'calendarsystem_gregorian');
+        }
+
+        $format = str_replace( array(
+                                    "%p",
+                                    "%P"
+                                    ),
+                               array(
+                                    ($date["hours"] < 12 ? $AMstring : $PMstring),
+                                    ($date["hours"] < 12 ? $amstring : $pmstring)
+                                    ),
+                              $format);
+
+        return userdate_old($date, $format, $timezone, $fixday, $fixhour);
+    }
+
+       public function today()
+       {
+               list($y, $m, $d) = explode( "-", date("Y-m-d"));
+
+               return array((int)$m, (int)$d, (int)$y);
+       }
+
+       public function get_month_names()
+       {
+               $months = array();
+
+           for ($i=1; $i<=12; $i++) {
+               $months[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), '%B');
+           }
+
+           return $months;
+       }
+
+       public function get_min_year()
+       {
+               return 1970;
+       }
+
+       public function get_max_year()
+       {
+               return 2020;
+       }
+
+    public function gmmktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) {
+        return gmmktime($hour, $minute, $second, $month, $day, $year);
+    }
+
+    public function mktime($hour=null, $minute=null, $second=null, $month=null, $day=null, $year=null) {
+        return mktime($hour, $minute, $second, $month, $day, $year);
+    }
+
+    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)));
+    }
+}
+?>
\ 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 (file)
index 0000000..c0df03a
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+$string['am'] = 'am';
+$string['am_caps'] = 'AM';
+$string['name'] = 'Gregorian';
+$string['pluginname'] = 'Gregorian calendar system';
+$string['pm'] = 'pm';
+$string['pm_caps'] = 'PM';
+?>
\ 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 (file)
index 0000000..2cb6e5f
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+$string['am'] = 'صبح';
+$string['am_caps'] = 'صبح';
+$string['name'] = 'میلادی';
+$string['pluginname'] = 'تقویم میلادی';
+$string['pm'] = 'عصر';
+$string['pm_caps'] = 'عصر';
+?>
\ No newline at end of file
diff --git a/calendarsystem/gregorian/version.php b/calendarsystem/gregorian/version.php
new file mode 100644 (file)
index 0000000..ae02452
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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 (file)
index 0000000..54ea267
--- /dev/null
@@ -0,0 +1,250 @@
+<?php
+
+class calendarsystem_plugin_hijri extends calendarsystem_plugin_base
+{
+/*
+    private function isleap($year) {
+        return (((year * 11) + 14) % 30) < 11;
+    }
+*/
+    public function calendar_days_in_month($m, $y)
+    {
+        $temp = $this->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 (file)
index 0000000..04f02d0
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+$string['am'] = 'am';
+$string['am_caps'] = 'AM';
+$string['name'] = 'Hijri';
+$string['month1'] = 'Muḥarram';
+$string['month2'] = 'Ṣafar';
+$string['month3'] = 'Rabīʿ al-Awwal';
+$string['month4'] = 'Rabīʿ al-Thānī';
+$string['month5'] = 'Jumādā al-Ūlā';
+$string['month6'] = 'Jumādā al-Thānī';
+$string['month7'] = 'Rajab';
+$string['month8'] = 'Shaʿbān';
+$string['month9'] = 'Ramaḍān';
+$string['month10'] = 'Shawwāl';
+$string['month11'] = 'Dhū al-Qaʿda';
+$string['month12'] = 'Dhū al-Ḥijja';
+$string['pm'] = 'pm';
+$string['pm_caps'] = 'PM';
+$string['weekday0'] = 'Sunday';
+$string['weekday1'] = 'Monday';
+$string['weekday2'] = 'Tuesday';
+$string['weekday3'] = 'Wednesday';
+$string['weekday4'] = 'Thursday';
+$string['weekday5'] = 'Friday';
+$string['weekday6'] = 'Saturday';
+$string['pluginname'] = 'Hijri calendar system';
+?>
\ 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 (file)
index 0000000..233d149
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+$string['am'] = 'صبح';
+$string['am_caps'] = 'صبح';
+$string['name'] = 'هجری قمری';
+$string['month1'] = 'محرم';
+$string['month2'] = 'صفر';
+$string['month3'] = 'ربیع‌الاول';
+$string['month4'] = 'ربیع‌الثانی';
+$string['month5'] = 'جمادی‌الاول';
+$string['month6'] = 'جمادی‌الثانی';
+$string['month7'] = 'رجب';
+$string['month8'] = 'شعبان';
+$string['month9'] = 'رمضان';
+$string['month10'] = 'شوال';
+$string['month11'] = 'ذیقعده';
+$string['month12'] = 'ذیحجه';
+$string['pm'] = 'عصر';
+$string['pm_caps'] = 'عصر';
+$string['weekday0'] = 'یکشنبه';
+$string['weekday1'] = 'دوشنبه';
+$string['weekday2'] = 'سه‌شنبه';
+$string['weekday3'] = 'چهارشنبه';
+$string['weekday4'] = 'پنج‌شنبه';
+$string['weekday5'] = 'جمعه';
+$string['weekday6'] = 'شنبه';
+$string['pluginname'] = 'تقویم هجری قمری';
+?>
\ No newline at end of file
diff --git a/calendarsystem/hijri/version.php b/calendarsystem/hijri/version.php
new file mode 100644 (file)
index 0000000..64024e6
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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 (file)
index 0000000..8397956
--- /dev/null
@@ -0,0 +1,175 @@
+<?php
+
+define('NO_OUTPUT_BUFFERING', true);
+
+require('../config.php');
+require_once($CFG->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 (file)
index 0000000..dd5e435
--- /dev/null
@@ -0,0 +1,289 @@
+<?php
+class calendarsystem_plugin_jalali extends calendarsystem_plugin_base
+{
+       public function calendar_days_in_month($m, $y)
+       {
+               if ($m <= 6)
+                       return 31;
+               elseif ($m != 12 or $this->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 (file)
index 0000000..64a7a86
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+$string['am'] = 'am';
+$string['am_caps'] = 'AM';
+$string['name'] = 'Persian';
+$string['month1'] = 'Farvardin';
+$string['month2'] = 'Ordibehesht';
+$string['month3'] = 'Khordad';
+$string['month4'] = 'Tir';
+$string['month5'] = 'Mordad';
+$string['month6'] = 'Shahrivar';
+$string['month7'] = 'Mehr';
+$string['month8'] = 'Aban';
+$string['month9'] = 'Azar';
+$string['month10'] = 'Dey';
+$string['month11'] = 'Bahman';
+$string['month12'] = 'Esfand';
+$string['pm'] = 'pm';
+$string['pm_caps'] = 'PM';
+$string['weekday0'] = 'Sunday';
+$string['weekday1'] = 'Monday';
+$string['weekday2'] = 'Tuesday';
+$string['weekday3'] = 'Wednesday';
+$string['weekday4'] = 'Thursday';
+$string['weekday5'] = 'Friday';
+$string['weekday6'] = 'Saturday';
+$string['pluginname'] = 'Persian calendar system';
+?>
\ 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 (file)
index 0000000..35d662c
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+$string['am'] = 'صبح';
+$string['am_caps'] = 'صبح';
+$string['name'] = 'خورشیدی';
+$string['month1'] = 'فروردین';
+$string['month2'] = 'اردیبهشت';
+$string['month3'] = 'خرداد';
+$string['month4'] = 'تیر';
+$string['month5'] = 'مرداد';
+$string['month6'] = 'شهریور';
+$string['month7'] = 'مهر';
+$string['month8'] = 'آبان';
+$string['month9'] = 'آذر';
+$string['month10'] = 'دی';
+$string['month11'] = 'بهمن';
+$string['month12'] = 'اسفند';
+$string['pm'] = 'عصر';
+$string['pm_caps'] = 'عصر';
+$string['weekday0'] = 'یکشنبه';
+$string['weekday1'] = 'دوشنبه';
+$string['weekday2'] = 'سه‌شنبه';
+$string['weekday3'] = 'چهارشنبه';
+$string['weekday4'] = 'پنج‌شنبه';
+$string['weekday5'] = 'جمعه';
+$string['weekday6'] = 'شنبه';
+$string['pluginname'] = 'تقویم هجری شمسی';
+?>
\ No newline at end of file
diff --git a/calendarsystem/jalali/version.php b/calendarsystem/jalali/version.php
new file mode 100644 (file)
index 0000000..bb39774
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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 (file)
index 0000000..cc6b69d
--- /dev/null
@@ -0,0 +1,341 @@
+<?php
+/**
+ * General exception thrown by the {@link calendarsystem_update_checker} class
+ */
+class calendarsystem_update_checker_exception extends moodle_exception {
+
+    /**
+     * @param string $errorcode exception description identifier
+     * @param mixed $debuginfo debugging data to display
+     */
+    public function __construct($errorcode, $debuginfo=null) {
+        parent::__construct($errorcode, 'calendarsystem', '', null, print_r($debuginfo, true));
+    }
+}
+
+class calendarsystem_update_checker {
+
+    /** @var calendarsystem_update_checker holds the singleton instance */
+    protected static $singletoninstance;
+    /** @var null|int the timestamp of when the most recent response was fetched */
+    protected $recentfetch = null;
+    /** @var null|array the recent response from the update notification provider */
+    protected $recentresponse = null;
+    /** @var null|string the numerical version of the local Moodle code */
+    protected $currentversion = null;
+    /** @var null|string the release info of the local Moodle code */
+    protected $currentrelease = null;
+    /** @var null|string branch of the local Moodle code */
+    protected $currentbranch = null;
+    /** @var array of (string)frankestyle => (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 (file)
index 0000000..24c4d6d
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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)
index 06f7435..983a7e0 100644 (file)
@@ -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
 //--------------------------------------------------------------------------------
index c1a6f80..6fcdb8d 100644 (file)
@@ -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;
         }
index 10e12e1..03b2a98 100644 (file)
@@ -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 : '';
 
index 7d91e4b..96ac9de 100644 (file)
@@ -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 (file)
index 0000000..51b607c
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+$string['preferredcalendar'] = 'Preferred calendar';
+$string['helpcalendarsystem'] = 'helpcalendarsystem';
+$string['changecalendar'] = 'change';
+$string['checkforupdates'] = 'Check for available updates';
+$string['configcalendarsystem'] = 'Default calendar';
+$string['forcecalendarsystem'] = 'Force calendar';
+$string['system'] = 'Calendar';
+$string['calendarsystem'] = 'Calendar system';
+$string['calendarsystems'] = 'Calendar systems';
+$string['calendarsystemdeleteconfirm'] = 'You are about to completely delete the calendar system \'{$a}\'. This will completely delete everything in the database associated with this plugin. Are you SURE you want to continue?';
+$string['calendarsystemsmanage'] = 'Manage calendar systems';
+$string['updateavailable'] = 'There is a newer calendar system core version available!';
+$string['updateavailable_moreinfo'] = 'More info...';
+$string['updateavailable_version'] = 'Version {$a}';
+$string['updateavailableforplugin'] = 'There is a newer version for {$a} calendar system plugin available!';
+$string['updateavailablenot'] = 'Your calendar system code is up-to-date!';
+$string['updatecheck'] = 'Check for CalendarSystem update';
+?>
\ No newline at end of file
index e65e1ea..630dbf6 100644 (file)
@@ -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';
index d221217..ffe4f85 100644 (file)
@@ -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:
index cb6b597..ac6eb77 100644 (file)
@@ -93,6 +93,7 @@
         <FIELD NAME="groupmodeforce" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
         <FIELD NAME="defaultgroupingid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="default grouping used in course modules, does not have key intentionally"/>
         <FIELD NAME="lang" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false"/>
+        <FIELD NAME="calendarsystem" TYPE="char" LENGTH="20" NOTNULL="false" DEFAULT="" SEQUENCE="false"/>
         <FIELD NAME="theme" TYPE="char" LENGTH="50" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
         <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
         <FIELD NAME="city" TYPE="char" LENGTH="120" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="country" TYPE="char" LENGTH="2" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="lang" TYPE="char" LENGTH="30" NOTNULL="true" DEFAULT="en" SEQUENCE="false"/>
+        <FIELD NAME="calendarsystem" TYPE="char" LENGTH="20" NOTNULL="false" DEFAULT="" SEQUENCE="false"/>
         <FIELD NAME="theme" TYPE="char" LENGTH="50" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="timezone" TYPE="char" LENGTH="100" NOTNULL="true" DEFAULT="99" SEQUENCE="false"/>
         <FIELD NAME="firstaccess" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
index f4cb2c5..d578e84 100644 (file)
@@ -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;
         }
index 0bc6a77..cf4f884 100644 (file)
@@ -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;
         }
index a0fae10..e01f2b6 100644 (file)
@@ -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.
index ecf4917..27fb471 100644 (file)
@@ -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
 
index 42489b1..9b40e63 100644 (file)
@@ -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');
index 5e45492..53a9ad6 100644 (file)
@@ -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;