Merge branch 'MDL-18375_master' of git://github.com/markn86/moodle
authorDamyon Wiese <damyon@moodle.com>
Mon, 9 Sep 2013 02:41:12 +0000 (10:41 +0800)
committerDamyon Wiese <damyon@moodle.com>
Mon, 9 Sep 2013 02:41:12 +0000 (10:41 +0800)
24 files changed:
calendar/classes/type_base.php [new file with mode: 0644]
calendar/classes/type_factory.php [new file with mode: 0644]
calendar/tests/calendartype_test.php [new file with mode: 0644]
calendar/tests/calendartype_test_example.php [new file with mode: 0644]
calendar/type/gregorian/classes/structure.php [new file with mode: 0644]
calendar/type/gregorian/lang/en/calendartype_gregorian.php [new file with mode: 0644]
calendar/type/gregorian/version.php [new file with mode: 0644]
course/edit_form.php
lang/en/admin.php
lang/en/calendar.php
lang/en/plugin.php
lib/classes/component.php
lib/db/install.xml
lib/db/upgrade.php
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/moodlelib.php
lib/pluginlib.php
user/editlib.php
user/profile/field/datetime/define.class.php
user/profile/field/datetime/field.class.php
user/profile/field/datetime/lang/en/profilefield_datetime.php
user/profile/field/datetime/version.php
version.php

diff --git a/calendar/classes/type_base.php b/calendar/classes/type_base.php
new file mode 100644 (file)
index 0000000..6458220
--- /dev/null
@@ -0,0 +1,116 @@
+<?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/>.
+
+namespace core_calendar;
+
+/**
+ * Defines functions used by calendar type plugins.
+ *
+ * This library provides a unified interface for calendar types.
+ *
+ * @package core_calendar
+ * @copyright 2008 onwards Foodle Group {@link http://foodle.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class type_base {
+
+    /**
+     * Returns a list of all the possible days for all months.
+     *
+     * This is used to generate the select box for the days
+     * in the date selector elements. Some months contain more days
+     * than others so this function should return all possible days as
+     * we can not predict what month will be chosen (the user
+     * may have JS turned off and we need to support this situation in
+     * Moodle).
+     *
+     * @return array the days
+     */
+    public abstract function get_days();
+
+    /**
+     * Returns a list of all the names of the months.
+     *
+     * @return array the month names
+     */
+    public abstract function get_months();
+
+    /**
+     * Returns the minimum year of the calendar.
+     *
+     * @return int the minumum year
+     */
+    public abstract function get_min_year();
+
+    /**
+     * Returns the maximum year of the calendar.
+     *
+     * @return int the max year
+     */
+    public abstract function get_max_year();
+
+    /**
+     * Returns a formatted string that represents a date in user time.
+     *
+     * @param int $date the timestamp in UTC, as obtained from the database
+     * @param string $format strftime format
+     * @param int|float|string $timezone the timezone to use
+     *        {@link http://docs.moodle.org/dev/Time_API#Timezone}
+     * @param bool $fixday if true then the leading zero from %d is removed,
+     *        if false then the leading zero is maintained
+     * @param bool $fixhour if true then the leading zero from %I is removed,
+     *        if false then the leading zero is maintained
+     * @return string the formatted date/time
+     */
+    public abstract function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour);
+
+    /**
+     * Given a $time timestamp in GMT (seconds since epoch), returns an array that represents
+     * the date in user time.
+     *
+     * @param int $time timestamp in GMT
+     * @param float|int|string $timezone the timezone to use to calculate the time
+     *        {@link http://docs.moodle.org/dev/Time_API#Timezone}
+     * @return array an array that represents the date in user time
+     */
+    public abstract function timestamp_to_date_array($time, $timezone);
+
+    /**
+     * Provided with a day, month, year, hour and minute in the specific
+     * calendar type convert it into the equivalent Gregorian date.
+     *
+     * @param int $year
+     * @param int $month
+     * @param int $day
+     * @param int $hour
+     * @param int $minute
+     * @return array the converted day, month and year.
+     */
+    public abstract function convert_to_gregorian($year, $month, $day, $hour = 0, $minute = 0);
+
+    /**
+     * Provided with a day, month, year, hour and minute in a Gregorian date
+     * convert it into the specific calendar type date.
+     *
+     * @param int $year
+     * @param int $month
+     * @param int $day
+     * @param int $hour
+     * @param int $minute
+     * @return array the converted day, month and year.
+     */
+    public abstract function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0);
+}
diff --git a/calendar/classes/type_factory.php b/calendar/classes/type_factory.php
new file mode 100644 (file)
index 0000000..535dd2b
--- /dev/null
@@ -0,0 +1,91 @@
+<?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/>.
+
+namespace core_calendar;
+
+/**
+ * Class \core_calendar\type_factory.
+ *
+ * Factory class producing required subclasses of {@link \core_calendar\type_base}.
+ *
+ * @package core_calendar
+ * @copyright 2008 onwards Foodle Group {@link http://foodle.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class type_factory {
+
+    /**
+     * Returns an instance of the currently used calendar type.
+     *
+     * @param string|null $type the calendar type to use, if none provided use logic to determine
+     * @return calendartype_* the created calendar_type class
+     * @throws coding_exception if the calendar type file could not be loaded
+     */
+    public static function get_calendar_instance($type = null) {
+        if (is_null($type)) {
+            $type = self::get_calendar_type();
+        }
+
+        $class = "\\calendartype_$type\\structure";
+
+        // Ensure the calendar type exists. It may occur that a user has selected a calendar type, which was then
+        // deleted. If this happens we want to fall back on the Gregorian calendar type.
+        if (!class_exists($class)) {
+            $class = "\\calendartype_gregorian\\structure";
+        }
+
+        return new $class();
+    }
+
+    /**
+     * Returns a list of calendar typess available for use.
+     *
+     * @return array the list of calendar types
+     */
+    public static function get_list_of_calendar_types() {
+        $calendars = array();
+        $calendardirs = \core_component::get_plugin_list('calendartype');
+
+        foreach ($calendardirs as $name => $location) {
+            $calendars[$name] = get_string('name', "calendartype_{$name}");
+        }
+
+        return $calendars;
+    }
+
+    /**
+     * Returns the current calendar type in use.
+     *
+     * @return string the current calendar type being used
+     */
+    public static function get_calendar_type() {
+        global $CFG, $USER, $SESSION, $COURSE;
+
+        if (!empty($COURSE->id) and $COURSE->id != SITEID and !empty($COURSE->calendartype)) { // Course calendartype can override all other settings for this page.
+            $return = $COURSE->calendartype;
+        } else if (!empty($SESSION->calendartype)) { // Session calendartype can override other settings.
+            $return = $SESSION->calendartype;
+        } else if (!empty($USER->calendartype)) {
+            $return = $USER->calendartype;
+        } else if (!empty($CFG->calendartype)) {
+            $return = $CFG->calendartype;
+        } else {
+            $return = 'gregorian';
+        }
+
+        return $return;
+    }
+}
diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php
new file mode 100644 (file)
index 0000000..10e72ea
--- /dev/null
@@ -0,0 +1,282 @@
+<?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/>.
+
+/**
+ * This file contains the class that handles testing the calendar type system.
+ *
+ * @package core_calendar
+ * @copyright 2013 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+// The test calendar type.
+require_once($CFG->dirroot . '/calendar/tests/calendartype_test_example.php');
+
+// Used to test the dateselector elements.
+require_once($CFG->libdir . '/form/dateselector.php');
+require_once($CFG->libdir . '/form/datetimeselector.php');
+
+// Used to test the user datetime profile field.
+require_once($CFG->dirroot . '/user/profile/lib.php');
+require_once($CFG->dirroot . '/user/profile/definelib.php');
+require_once($CFG->dirroot . '/user/profile/index_field_form.php');
+
+/**
+ * Unit tests for the calendar type system.
+ *
+ * @package core_calendar
+ * @copyright 2013 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since Moodle 2.6
+ */
+class core_calendar_type_testcase extends advanced_testcase {
+
+    /**
+     * The test user.
+     */
+    private $user;
+
+    /**
+     * Test set up.
+     */
+    protected function setUp() {
+        // The user we are going to test this on.
+        $this->user = self::getDataGenerator()->create_user();
+        self::setUser($this->user);
+    }
+
+    /**
+     * Test that setting the calendar type works.
+     */
+    public function test_calendar_type_set() {
+        // We want to reset the test data after this run.
+        $this->resetAfterTest();
+
+        // Test setting it as the 'Test' calendar type.
+        $this->set_calendar_type('test');
+        $this->assertEquals('test', \core_calendar\type_factory::get_calendar_type());
+
+        // Test setting it as the 'Gregorian' calendar type.
+        $this->set_calendar_type('gregorian');
+        $this->assertEquals('gregorian', \core_calendar\type_factory::get_calendar_type());
+    }
+
+    /**
+     * Test that calling core Moodle functions responsible for displaying the date
+     * have the same results as directly calling the same function in the calendar type.
+     */
+    public function test_calendar_type_core_functions() {
+        // We want to reset the test data after this run.
+        $this->resetAfterTest();
+
+        // Test that the core functions reproduce the same results as the Gregorian calendar.
+        $this->core_functions_test('gregorian');
+
+        // Test that the core functions reproduce the same results as the test calendar.
+        $this->core_functions_test('test');
+    }
+
+    /**
+     * Test that dates selected using the date selector elements are being saved as unixtime, and that the
+     * unixtime is being converted back to a valid date to display in the date selector elements for
+     * different calendar types.
+     */
+    public function test_calendar_type_dateselector_elements() {
+        // We want to reset the test data after this run.
+        $this->resetAfterTest();
+
+        // Check converting dates to Gregorian when submitting a date selector element works. Note: the test
+        // calendar is 2 years, 2 months, 2 days, 2 hours and 2 minutes ahead of the Gregorian calendar.
+        $date1 = array();
+        $date1['day'] = 4;
+        $date1['month'] = 7;
+        $date1['year'] = 2013;
+        $date1['hour'] = 0;
+        $date1['minute'] = 0;
+        $date1['timestamp'] = 1372896000;
+        $this->convert_dateselector_to_unixtime_test('dateselector', 'gregorian', $date1);
+
+        $date2 = array();
+        $date2['day'] = 7;
+        $date2['month'] = 9;
+        $date2['year'] = 2015;
+        $date2['hour'] = 0; // The dateselector element does not have hours.
+        $date2['minute'] = 0; // The dateselector element does not have minutes.
+        $date2['timestamp'] = 1372896000;
+        $this->convert_dateselector_to_unixtime_test('dateselector', 'test', $date2);
+
+        $date3 = array();
+        $date3['day'] = 4;
+        $date3['month'] = 7;
+        $date3['year'] = 2013;
+        $date3['hour'] = 23;
+        $date3['minute'] = 15;
+        $date3['timestamp'] = 1372979700;
+        $this->convert_dateselector_to_unixtime_test('datetimeselector', 'gregorian', $date3);
+
+        $date4 = array();
+        $date4['day'] = 7;
+        $date4['month'] = 9;
+        $date4['year'] = 2015;
+        $date4['hour'] = 1;
+        $date4['minute'] = 17;
+        $date4['timestamp'] = 1372979700;
+        $this->convert_dateselector_to_unixtime_test('datetimeselector', 'test', $date4);
+
+        // The date selector element values are set by using the function usergetdate, here we want to check that
+        // the unixtime passed is being successfully converted to the correct values for the calendar type.
+        $this->convert_unixtime_to_dateselector_test('gregorian', $date3);
+        $this->convert_unixtime_to_dateselector_test('test', $date4);
+    }
+
+    /**
+     * Test that the user profile field datetime minimum and maximum year settings are saved as the
+     * equivalent Gregorian years.
+     */
+    public function test_calendar_type_datetime_field_submission() {
+        // We want to reset the test data after this run.
+        $this->resetAfterTest();
+
+        // Create an array with the input values and expected values once submitted.
+        $date = array();
+        $date['inputminyear'] = '1970';
+        $date['inputmaxyear'] = '2013';
+        $date['expectedminyear'] = '1970';
+        $date['expectedmaxyear'] = '2013';
+        $this->datetime_field_submission_test('gregorian', $date);
+
+        // The test calendar is 2 years, 2 months, 2 days in the future, so when the year 1970 is submitted,
+        // the year 1967 should be saved in the DB, as 1/1/1970 converts to 30/10/1967 in Gregorian.
+        $date['expectedminyear'] = '1967';
+        $date['expectedmaxyear'] = '2010';
+        $this->datetime_field_submission_test('test', $date);
+    }
+
+    /**
+     * Test all the core functions that use the calendar type system.
+     *
+     * @param string $type the calendar type we want to test
+     */
+    private function core_functions_test($type) {
+        $this->set_calendar_type($type);
+
+        // Get the calendar.
+        $calendar = \core_calendar\type_factory::get_calendar_instance();
+
+        // Test the userdate function.
+        $this->assertEquals($calendar->timestamp_to_date_string($this->user->timecreated, '', 99, true, true),
+            userdate($this->user->timecreated));
+    }
+
+    /**
+     * Simulates submitting a form with a date selector element and tests that the chosen dates
+     * are converted into unixtime before being saved in DB.
+     *
+     * @param string $element the form element we are testing
+     * @param string $type the calendar type we want to test
+     * @param array $date the date variables
+     */
+    private function convert_dateselector_to_unixtime_test($element, $type, $date) {
+        $this->set_calendar_type($type);
+
+        if ($element == 'dateselector') {
+            $el = new MoodleQuickForm_date_selector('dateselector', null, array('timezone' => 0.0, 'step' => 1));
+        } else {
+            $el = new MoodleQuickForm_date_time_selector('dateselector', null, array('timezone' => 0.0, 'step' => 1));
+        }
+        $el->_createElements();
+        $submitvalues = array('dateselector' => $date);
+
+        $this->assertSame($el->exportValue($submitvalues), array('dateselector' => $date['timestamp']));
+    }
+
+    /**
+     * Test converting dates from unixtime to a date for the calendar type specified.
+     *
+     * @param string $type the calendar type we want to test
+     * @param array $date the date variables
+     */
+    private function convert_unixtime_to_dateselector_test($type, $date) {
+        $this->set_calendar_type($type);
+
+        // Get the calendar.
+        $calendar = \core_calendar\type_factory::get_calendar_instance();
+
+        $usergetdate = $calendar->timestamp_to_date_array($date['timestamp'], 0.0);
+        $comparedate = array(
+            'minute' => $usergetdate['minutes'],
+            'hour' => $usergetdate['hours'],
+            'day' => $usergetdate['mday'],
+            'month' => $usergetdate['mon'],
+            'year' => $usergetdate['year'],
+            'timestamp' => $date['timestamp']
+        );
+
+        $this->assertEquals($comparedate, $date);
+    }
+
+    /**
+     * Test saving the minimum and max year settings for the user datetime field.
+     *
+     * @param string $type the calendar type we want to test
+     * @param array $date the date variables
+     */
+    private function datetime_field_submission_test($type, $date) {
+        $this->set_calendar_type($type);
+
+        // Get the data we are submitting for the form.
+        $formdata = array();
+        $formdata['id'] = 0;
+        $formdata['shortname'] = 'Shortname';
+        $formdata['name'] = 'Name';
+        $formdata['param1'] = $date['inputminyear'];
+        $formdata['param2'] = $date['inputmaxyear'];
+
+        // Mock submitting this.
+        field_form::mock_submit($formdata);
+
+        // Create the user datetime form.
+        $form = new field_form(null, 'datetime');
+
+        // Get the data from the submission.
+        $submissiondata = $form->get_data();
+        // On the user profile field page after get_data, the function define_save is called
+        // in the field base class, which then calls the field's function define_save_preprocess.
+        $field = new profile_define_datetime();
+        $submissiondata = $field->define_save_preprocess($submissiondata);
+
+        // Create an array we want to compare with the date passed.
+        $comparedate = $date;
+        $comparedate['expectedminyear'] = $submissiondata->param1;
+        $comparedate['expectedmaxyear'] = $submissiondata->param2;
+
+        $this->assertEquals($comparedate, $date);
+    }
+
+    /**
+     * Set the calendar type for this user.
+     *
+     * @param string $type the calendar type we want to set
+     */
+    private function set_calendar_type($type) {
+        $this->user->calendartype = $type;
+        session_set_user($this->user);
+    }
+}
diff --git a/calendar/tests/calendartype_test_example.php b/calendar/tests/calendartype_test_example.php
new file mode 100644 (file)
index 0000000..679422e
--- /dev/null
@@ -0,0 +1,176 @@
+<?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/>.
+
+namespace calendartype_test;
+use \core_calendar\type_base;
+
+/**
+ * Handles calendar functions for the test calendar.
+ *
+ * The test calendar is going to be 2 years, 2 days, 2 hours and 2 minutes
+ * in the future of the Gregorian calendar.
+ *
+ * @package core_calendar
+ * @copyright 2013 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class structure extends type_base {
+
+    /**
+     * Returns a list of all the possible days for all months.
+     *
+     * This is used to generate the select box for the days
+     * in the date selector elements. Some months contain more days
+     * than others so this function should return all possible days as
+     * we can not predict what month will be chosen (the user
+     * may have JS turned off and we need to support this situation in
+     * Moodle).
+     *
+     * @return array the days
+     */
+    public function get_days() {
+        $days = array();
+
+        for ($i = 1; $i <= 31; $i++) {
+            $days[$i] = $i;
+        }
+
+        return $days;
+    }
+
+    /**
+     * Returns a list of all the names of the months.
+     *
+     * @return array the month names
+     */
+    public function get_months() {
+        $months = array();
+
+        for ($i = 1; $i <= 12; $i++) {
+            $months[$i] = $i;
+        }
+
+        return $months;
+    }
+
+    /**
+     * Returns the minimum year of the calendar.
+     *
+     * @return int the minumum year
+     */
+    public function get_min_year() {
+        return 1970;
+    }
+
+    /**
+     * Returns the maximum year of the calendar.
+     *
+     * @return int the max year
+     */
+    public function get_max_year() {
+        return 2050;
+    }
+
+    /**
+     * Returns a formatted string that represents a date in user time.
+     *
+     * @param int $date the timestamp in UTC, as obtained from the database
+     * @param string $format strftime format
+     * @param int|float|string $timezone the timezone to use
+     *        {@link http://docs.moodle.org/dev/Time_API#Timezone}
+     * @param bool $fixday if true then the leading zero from %d is removed,
+     *        if false then the leading zero is maintained
+     * @param bool $fixhour if true then the leading zero from %I is removed,
+     *        if false then the leading zero is maintained
+     * @return string the formatted date/time
+     */
+    public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour) {
+        return '';
+    }
+
+    /**
+     * Given a $time timestamp in GMT (seconds since epoch), returns an array that represents
+     * the date in user time.
+     *
+     * @param int $time timestamp in GMT
+     * @param float|int|string $timezone the timezone to use to calculate the time
+     *        {@link http://docs.moodle.org/dev/Time_API#Timezone}
+     * @return array an array that represents the date in user time
+     */
+    public function timestamp_to_date_array($time, $timezone) {
+        $gregoriancalendar = \core_calendar\type_factory::get_calendar_instance('gregorian');
+        $date = $gregoriancalendar->timestamp_to_date_array($time, $timezone);
+        $newdate = $this->convert_from_gregorian($date['year'], $date['mon'], $date['mday'],
+            $date['hours'], $date['minutes']);
+
+        $date['year'] = $newdate['year'];
+        $date['mon'] = $newdate['month'];
+        $date['mday'] = $newdate['day'];
+        $date['hours'] = $newdate['hour'];
+        $date['minutes']  = $newdate['minute'];
+
+        return $date;
+    }
+
+    /**
+     * Provided with a day, month, year, hour and minute
+     * convert it into the equivalent Gregorian date.
+     *
+     * @param int $year
+     * @param int $month
+     * @param int $day
+     * @param int $hour
+     * @param int $minute
+     * @return array the converted day, month, year, hour and minute.
+     */
+    public function convert_to_gregorian($year, $month, $day, $hour = 0, $minute = 0) {
+        $timestamp = make_timestamp($year, $month, $day, $hour, $minute);
+        $date = date('Y/n/j/H/i', strtotime('-2 year, -2 months, -2 days, -2 hours, -2 minutes', $timestamp));
+
+        list($year, $month, $day, $hour, $minute) = explode('/', $date);
+
+        return array('year' => (int) $year,
+                     'month' => (int) $month,
+                     'day' => (int) $day,
+                     'hour' => (int) $hour,
+                     'minute' => (int) $minute);
+
+    }
+
+    /**
+     * Provided with a day, month, year, hour and minute in a Gregorian date
+     * convert it into the specific calendar type date.
+     *
+     * @param int $year
+     * @param int $month
+     * @param int $day
+     * @param int $hour
+     * @param int $minute
+     * @return array the converted day, month, year, hour and minute.
+     */
+    public function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0) {
+        $timestamp = make_timestamp($year, $month, $day, $hour, $minute);
+        $date = date('Y/n/j/H/i', strtotime('+2 year, +2 months, +2 days, +2 hours, +2 minutes', $timestamp));
+
+        list($year, $month, $day, $hour, $minute) = explode('/', $date);
+
+        return array('year' => (int) $year,
+                     'month' => (int) $month,
+                     'day' => (int) $day,
+                     'hour' => (int) $hour,
+                     'minute' => (int) $minute);
+    }
+}
diff --git a/calendar/type/gregorian/classes/structure.php b/calendar/type/gregorian/classes/structure.php
new file mode 100644 (file)
index 0000000..d209864
--- /dev/null
@@ -0,0 +1,232 @@
+<?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/>.
+
+namespace calendartype_gregorian;
+use core_calendar\type_base;
+
+/**
+ * Handles calendar functions for the gregorian calendar.
+ *
+ * @package calendartype_gregorian
+ * @copyright 2008 onwards Foodle Group {@link http://foodle.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class structure extends type_base {
+
+    /**
+     * Returns a list of all the possible days for all months.
+     *
+     * This is used to generate the select box for the days
+     * in the date selector elements. Some months contain more days
+     * than others so this function should return all possible days as
+     * we can not predict what month will be chosen (the user
+     * may have JS turned off and we need to support this situation in
+     * Moodle).
+     *
+     * @return array the days
+     */
+    public function get_days() {
+        $days = array();
+
+        for ($i = 1; $i <= 31; $i++) {
+            $days[$i] = $i;
+        }
+
+        return $days;
+    }
+
+    /**
+     * Returns a list of all the names of the months.
+     *
+     * @return array the month names
+     */
+    public function get_months() {
+        $months = array();
+
+        for ($i = 1; $i <= 12; $i++) {
+            $months[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), '%B');
+        }
+
+        return $months;
+    }
+
+    /**
+     * Returns the minimum year of the calendar.
+     *
+     * @return int the minumum year
+     */
+    public function get_min_year() {
+        return 1900;
+    }
+
+    /**
+     * Returns the maximum year of the calendar.
+     *
+     * @return int the max year
+     */
+    public function get_max_year() {
+        return 2050;
+    }
+
+    /**
+     * Returns a formatted string that represents a date in user time.
+     *
+     * Returns a formatted string that represents a date in user time
+     * <b>WARNING: note that the format is for strftime(), not date().</b>
+     * Because of a bug in most Windows time libraries, we can't use
+     * the nicer %e, so we have to use %d which has leading zeroes.
+     * A lot of the fuss in the function is just getting rid of these leading
+     * zeroes as efficiently as possible.
+     *
+     * If parameter fixday = true (default), then take off leading
+     * zero from %d, else maintain it.
+     *
+     * @param int $date the timestamp in UTC, as obtained from the database
+     * @param string $format strftime format
+     * @param int|float|string $timezone the timezone to use
+     *        {@link http://docs.moodle.org/dev/Time_API#Timezone}
+     * @param bool $fixday if true then the leading zero from %d is removed,
+     *        if false then the leading zero is maintained
+     * @param bool $fixhour if true then the leading zero from %I is removed,
+     *        if false then the leading zero is maintained
+     * @return string the formatted date/time
+     */
+    public function timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour) {
+        global $CFG;
+
+        if (empty($format)) {
+            $format = get_string('strftimedaydatetime', 'langconfig');
+        }
+
+        if (!empty($CFG->nofixday)) { // Config.php can force %d not to be fixed.
+            $fixday = false;
+        } else if ($fixday) {
+            $formatnoday = str_replace('%d', 'DD', $format);
+            $fixday = ($formatnoday != $format);
+            $format = $formatnoday;
+        }
+
+        // Note: This logic about fixing 12-hour time to remove unnecessary leading
+        // zero is required because on Windows, PHP strftime function does not
+        // support the correct 'hour without leading zero' parameter (%l).
+        if (!empty($CFG->nofixhour)) {
+            // Config.php can force %I not to be fixed.
+            $fixhour = false;
+        } else if ($fixhour) {
+            $formatnohour = str_replace('%I', 'HH', $format);
+            $fixhour = ($formatnohour != $format);
+            $format = $formatnohour;
+        }
+
+        // Add daylight saving offset for string timezones only, as we can't get dst for
+        // float values. if timezone is 99 (user default timezone), then try update dst.
+        if ((99 == $timezone) || !is_numeric($timezone)) {
+            $date += dst_offset_on($date, $timezone);
+        }
+
+        $timezone = get_user_timezone_offset($timezone);
+
+        // If we are running under Windows convert to windows encoding and then back to UTF-8
+        // (because it's impossible to specify UTF-8 to fetch locale info in Win32).
+        if (abs($timezone) > 13) { // Server time.
+            $datestring = date_format_string($date, $format, $timezone);
+            if ($fixday) {
+                $daystring  = ltrim(str_replace(array(' 0', ' '), '', strftime(' %d', $date)));
+                $datestring = str_replace('DD', $daystring, $datestring);
+            }
+            if ($fixhour) {
+                $hourstring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %I', $date)));
+                $datestring = str_replace('HH', $hourstring, $datestring);
+            }
+        } else {
+            $date += (int)($timezone * 3600);
+            $datestring = date_format_string($date, $format, $timezone);
+            if ($fixday) {
+                $daystring  = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %d', $date)));
+                $datestring = str_replace('DD', $daystring, $datestring);
+            }
+            if ($fixhour) {
+                $hourstring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %I', $date)));
+                $datestring = str_replace('HH', $hourstring, $datestring);
+            }
+        }
+
+        return $datestring;
+    }
+
+    /**
+     * Given a $time timestamp in GMT (seconds since epoch), returns an array that
+     * represents the date in user time.
+     *
+     * @param int $time Timestamp in GMT
+     * @param float|int|string $timezone offset's time with timezone, if float and not 99, then no
+     *        dst offset is applied {@link http://docs.moodle.org/dev/Time_API#Timezone}
+     * @return array an array that represents the date in user time
+     */
+    public function timestamp_to_date_array($time, $timezone) {
+        return usergetdate($time, $timezone);
+    }
+
+    /**
+     * Provided with a day, month, year, hour and minute in a specific
+     * calendar type convert it into the equivalent Gregorian date.
+     *
+     * In this function we don't need to do anything except pass the data
+     * back as an array. This is because the date received is Gregorian.
+     *
+     * @param int $year
+     * @param int $month
+     * @param int $day
+     * @param int $hour
+     * @param int $minute
+     * @return array the converted day, month, year, hour and minute.
+     */
+    public function convert_from_gregorian($year, $month, $day, $hour = 0, $minute = 0) {
+        $date = array();
+        $date['year'] = $year;
+        $date['month'] = $month;
+        $date['day'] = $day;
+        $date['hour'] = $hour;
+        $date['minute'] = $minute;
+
+        return $date;
+    }
+
+    /**
+     * Provided with a day, month, year, hour and minute in a specific
+     * calendar type convert it into the equivalent Gregorian date.
+     *
+     * In this function we don't need to do anything except pass the data
+     * back as an array. This is because the date received is Gregorian.
+     *
+     * @param int $year
+     * @param int $month
+     * @param int $day
+     * @param int $hour
+     * @param int $minute
+     * @return array the converted day, month, year, hour and minute.
+     */
+    public function convert_to_gregorian($year, $month, $day, $hour = 0, $minute = 0) {
+        $date = array();
+        $date['year'] = $year;
+        $date['month'] = $month;
+        $date['day'] = $day;
+        $date['hour'] = $hour;
+        $date['minute'] = $minute;
+
+        return $date;
+    }
+}
diff --git a/calendar/type/gregorian/lang/en/calendartype_gregorian.php b/calendar/type/gregorian/lang/en/calendartype_gregorian.php
new file mode 100644 (file)
index 0000000..9d2c5ba
--- /dev/null
@@ -0,0 +1,26 @@
+<?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/>.
+
+/**
+ * Strings for component 'calendartype_gregorian', language 'en'.
+ *
+ * @package calendartype_gregorian
+ * @copyright 2008 onwards Foodle Group {@link http://foodle.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['name'] = 'Gregorian';
+$string['pluginname'] = 'Gregorian calendar type';
diff --git a/calendar/type/gregorian/version.php b/calendar/type/gregorian/version.php
new file mode 100644 (file)
index 0000000..deeac17
--- /dev/null
@@ -0,0 +1,29 @@
+<?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 calendartype_gregorian
+ * @copyright 2008 onwards Foodle Group {@link http://foodle.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$plugin->version   = 2013082300; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2012120300; // Requires this Moodle version.
+$plugin->component = 'calendartype_gregorian'; // Full name of the plugin (used for diagnostics).
index d894efb..2dcbce2 100644 (file)
@@ -6,12 +6,18 @@ require_once($CFG->libdir.'/formslib.php');
 require_once($CFG->libdir.'/completionlib.php');
 require_once($CFG->libdir. '/coursecatlib.php');
 
+/**
+ * The form for handling editing a course.
+ */
 class course_edit_form extends moodleform {
     protected $course;
     protected $context;
 
+    /**
+     * Form definition.
+     */
     function definition() {
-        global $USER, $CFG, $DB, $PAGE;
+        global $CFG, $PAGE;
 
         $mform    = $this->_form;
         $PAGE->requires->yui_module('moodle-course-formatchooser', 'M.course.init_formatchooser',
@@ -38,8 +44,7 @@ class course_edit_form extends moodleform {
         $this->course  = $course;
         $this->context = $context;
 
-/// form definition with new course defaults
-//--------------------------------------------------------------------------------
+        // Form definition with new course defaults.
         $mform->addElement('header','general', get_string('general', 'form'));
 
         $mform->addElement('hidden', 'returnto', null);
@@ -194,6 +199,16 @@ class course_edit_form extends moodleform {
         $mform->addElement('select', 'lang', get_string('forcelanguage'), $languages);
         $mform->setDefault('lang', $courseconfig->lang);
 
+        // Multi-Calendar Support - see MDL-18375.
+        $calendartypes = \core_calendar\type_factory::get_list_of_calendar_types();
+        // We do not want to show this option unless there is more than one calendar type to display.
+        if (count($calendartypes) > 1) {
+            $calendars = array();
+            $calendars[''] = get_string('forceno');
+            $calendars += $calendartypes;
+            $mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendars);
+        }
+
         $options = range(0, 10);
         $mform->addElement('select', 'newsitems', get_string('newsitemsnumber'), $options);
         $mform->addHelpButton('newsitems', 'newsitemsnumber');
@@ -247,10 +262,8 @@ class course_edit_form extends moodleform {
             $mform->setDefault('enablecompletion', 0);
         }
 
-//--------------------------------------------------------------------------------
         enrol_course_edit_form($mform, $course, $context);
 
-//--------------------------------------------------------------------------------
         $mform->addElement('header','groups', get_string('groupsettingsheader', 'group'));
 
         $choices = array();
@@ -270,10 +283,7 @@ class course_edit_form extends moodleform {
         $options[0] = get_string('none');
         $mform->addElement('select', 'defaultgroupingid', get_string('defaultgrouping', 'group'), $options);
 
-//--------------------------------------------------------------------------------
-
-/// customizable role names in this course
-//--------------------------------------------------------------------------------
+        // Customizable role names in this course.
         $mform->addElement('header','rolerenaming', get_string('rolerenaming'));
         $mform->addHelpButton('rolerenaming', 'rolerenaming');
 
@@ -286,17 +296,18 @@ class course_edit_form extends moodleform {
             }
         }
 
-//--------------------------------------------------------------------------------
         $this->add_action_buttons();
-//--------------------------------------------------------------------------------
+
         $mform->addElement('hidden', 'id', null);
         $mform->setType('id', PARAM_INT);
 
-/// finally set the current form data
-//--------------------------------------------------------------------------------
+        // Finally set the current form data
         $this->set_data($course);
     }
 
+    /**
+     * Fill in the current page data for this course.
+     */
     function definition_after_data() {
         global $DB;
 
@@ -327,7 +338,13 @@ class course_edit_form extends moodleform {
         }
     }
 
-/// perform some extra moodle validation
+    /**
+     * Validation.
+     *
+     * @param array $data
+     * @param array $files
+     * @return array the errors that were found
+     */
     function validation($data, $files) {
         global $DB;
 
index d230f67..ef68ec9 100644 (file)
@@ -570,8 +570,9 @@ $string['gradeexport'] = 'Primary grade export methods';
 $string['guestroleid'] = 'Role for guest';
 $string['guestroleid_help'] = 'This role is automatically assigned to the guest user. It is also temporarily assigned to not enrolled users that enter the course via guest enrolment plugin.';
 $string['helpadminseesall'] = 'Do admins see all calendar events or just those that apply to themselves?';
-$string['helpcalendarsettings'] = 'Configure various calendar and date/time-related aspects of Moodle';
 $string['helpcalendarcustomexport'] = 'Enable custom date range export option in calendar exports. Calendar exports must be enabled before this is effective.';
+$string['helpcalendarsettings'] = 'Configure various calendar and date/time-related aspects of Moodle';
+$string['helpcalendartype'] = 'This is the calendar type that will be used throughout your site.';
 $string['helpexportlookahead'] = 'How many days in the future does the calendar look for events during export for the custom export option?';
 $string['helpexportlookback'] = 'How many days in the past does the calendar look for events during export for the custom export option?';
 $string['helpforcetimezone'] = 'You can allow users to individually select their timezone, or force a timezone for everyone.';
index 75d51b9..7a6a6af 100644 (file)
@@ -93,6 +93,7 @@ $string['export'] = 'Export';
 $string['exportbutton'] = 'Export';
 $string['exportcalendar'] = 'Export calendar';
 $string['for'] = 'for';
+$string['forcecalendartype'] = 'Force calendar';
 $string['fri'] = 'Fri';
 $string['friday'] = 'Friday';
 $string['generateurlbutton'] = 'Get calendar URL';
@@ -138,6 +139,7 @@ $string['pollinterval'] = 'Update interval';
 $string['pollinterval_help'] = 'How often you would like the calendar to update with new events.';
 $string['preferences'] = 'Preferences';
 $string['preferences_available'] = 'Your personal preferences';
+$string['preferredcalendar'] = 'Preferred calendar';
 $string['pref_lookahead'] = 'Upcoming events look-ahead';
 $string['pref_lookahead_help'] = 'This sets the (maximum) number of days in the future that an event has to start in in order to be displayed as an upcoming event. Events that start beyond this will never be displayed as upcoming. Please note that <strong>there is no guarantee</strong> that all events starting in this time frame will be displayed; if there are too many (more than the "Maximum upcoming events" preference) then the most distant events will not be shown.';
 $string['pref_maxevents'] = 'Maximum upcoming events';
index e65e1ea..f1e7958 100644 (file)
@@ -91,6 +91,8 @@ $string['type_cachelock'] = 'Cache lock handler';
 $string['type_cachelock_plural'] = 'Cache lock handlers';
 $string['type_cachestore'] = 'Cache store';
 $string['type_cachestore_plural'] = 'Cache stores';
+$string['type_calendartype'] = 'Calendar type';
+$string['type_calendartype_plural'] = 'Calendar types';
 $string['type_coursereport'] = 'Course report';
 $string['type_coursereport_plural'] = 'Course reports';
 $string['type_editor'] = 'Editor';
index 7d4949a..aa1a433 100644 (file)
@@ -364,6 +364,7 @@ $cache = '.var_export($cache, true).';
             'qtype'         => $CFG->dirroot.'/question/type',
             'mod'           => $CFG->dirroot.'/mod',
             'auth'          => $CFG->dirroot.'/auth',
+            'calendartype'  => $CFG->dirroot.'/calendar/type',
             'enrol'         => $CFG->dirroot.'/enrol',
             'message'       => $CFG->dirroot.'/message/output',
             'block'         => $CFG->dirroot.'/blocks',
index cb6b597..f97f836 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="calendartype" TYPE="char" LENGTH="30" NOTNULL="true" 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="calendartype" TYPE="char" LENGTH="30" NOTNULL="true" DEFAULT="gregorian" 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 494ec78..0fd05c3 100644 (file)
@@ -2363,5 +2363,28 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2013082700.00);
     }
 
+    if ($oldversion < 2013090500.01) {
+        // Define field calendartype to be added to course.
+        $table = new xmldb_table('course');
+        $field = new xmldb_field('calendartype', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null);
+
+        // Conditionally launch add field calendartype.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Define field calendartype to be added to user.
+        $table = new xmldb_table('user');
+        $field = new xmldb_field('calendartype', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'gregorian');
+
+        // Conditionally launch add field calendartype.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2013090500.01);
+    }
+
     return true;
 }
index f4cb2c5..4e94b09 100644 (file)
@@ -39,10 +39,11 @@ require_once($CFG->libdir . '/formslib.php');
  * @copyright 2007 Jamie Pratt <me@jamiep.org>
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class MoodleQuickForm_date_selector extends MoodleQuickForm_group
-{
+class MoodleQuickForm_date_selector extends MoodleQuickForm_group {
+
     /**
-     * Control the fieldnames for form elements
+     * Control the fieldnames for form elements.
+     *
      * startyear => int start of range of years that can be selected
      * stopyear => int last year that can be selected
      * timezone => int|float|string (optional) timezone modifier used for edge case only.
@@ -52,8 +53,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.
@@ -75,8 +76,12 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
      * @param array $options Options to control the element's display
      * @param mixed $attributes Either a typical HTML attribute string or an associative array
      */
-    function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null)
-    {
+    function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
+        // Get the calendar type used - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+        $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(),
+            'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false);
+
         $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
         $this->_persistantFreeze = true;
         $this->_appendName = true;
@@ -93,7 +98,10 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
                 }
             }
         }
-        form_init_date_js();
+        // The YUI2 calendar only supports the gregorian calendar type.
+        if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') {
+            form_init_date_js();
+        }
     }
 
     /**
@@ -101,28 +109,29 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
      *
      * @access private
      */
-    function _createElements()
-    {
+    function _createElements() {
         global $OUTPUT;
 
-        $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");
-        }
-        for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) {
+        // Get the calendar type used - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+        $days = $calendartype->get_days();
+        $months = $calendartype->get_months();
+        for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) {
             $years[$i] = $i;
         }
+
+        $this->_elements = array();
         // E_STRICT creating elements without forms is nasty because it internally uses $this
         $this->_elements[] = @MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true);
         $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true);
         $this->_elements[] = @MoodleQuickForm::createElement('select', 'year', get_string('year', 'form'), $years, $this->getAttributes(), true);
-        $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'),
-            array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs'));
+        // The YUI2 calendar only supports the gregorian calendar type so only display the calendar image if this is being used.
+        if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') {
+            $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'),
+                array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs'));
+        }
         // If optional we add a checkbox which the user can use to turn if on
-        if($this->_options['optional']) {
+        if ($this->_options['optional']) {
             $this->_elements[] = @MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
         }
         foreach ($this->_elements as $element){
@@ -141,16 +150,15 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
      * @param object $caller calling object
      * @return bool
      */
-    function onQuickFormEvent($event, $arg, &$caller)
-    {
+    function onQuickFormEvent($event, $arg, &$caller) {
         switch ($event) {
             case 'updateValue':
-                // constant values override both default and submitted ones
-                // default values are overriden by submitted
+                // Constant values override both default and submitted ones
+                // default values are overriden by submitted.
                 $value = $this->_findValue($caller->_constantValues);
                 if (null === $value) {
-                    // if no boxes were checked, then there is no value in the array
-                    // yet we don't want to display default value in this case
+                    // If no boxes were checked, then there is no value in the array
+                    // yet we don't want to display default value in this case.
                     if ($caller->isSubmitted()) {
                         $value = $this->_findValue($caller->_submitValues);
                     } else {
@@ -162,19 +170,20 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
                     $value = time();
                 }
                 if (!is_array($value)) {
-                    $currentdate = usergetdate($value, $this->_options['timezone']);
+                    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+                    $currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']);
                     $value = array(
                         'day' => $currentdate['mday'],
                         'month' => $currentdate['mon'],
                         'year' => $currentdate['year']);
-                    // If optional, default to off, unless a date was provided
-                     if($this->_options['optional']) {
+                    // If optional, default to off, unless a date was provided.
+                    if ($this->_options['optional']) {
                         $value['enabled'] = $requestvalue != 0;
                     }
                 } else {
                     $value['enabled'] = isset($value['enabled']);
                 }
-                if (null !== $value){
+                if (null !== $value) {
                     $this->setValue($value);
                 }
                 break;
@@ -208,8 +217,7 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
      *
      * @return string
      */
-    function toHtml()
-    {
+    function toHtml() {
         include_once('HTML/QuickForm/Renderer/Default.php');
         $renderer = new HTML_QuickForm_Renderer_Default();
         $renderer->setElementTemplate('{element}');
@@ -233,8 +241,7 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
      * @param bool $required Whether a group is required
      * @param string $error An error message associated with a group
      */
-    function accept(&$renderer, $required = false, $error = null)
-    {
+    function accept(&$renderer, $required = false, $error = null) {
         $renderer->renderElement($this, $required, $error);
     }
 
@@ -245,8 +252,7 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
      * @param bool $assoc specifies if returned array is associative
      * @return array
      */
-    function exportValue(&$submitValues, $assoc = false)
-    {
+    function exportValue(&$submitValues, $assoc = false) {
         $value = null;
         $valuearray = array();
         foreach ($this->_elements as $element){
@@ -263,13 +269,15 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
                     return $value;
                 }
             }
-
-            $value[$this->getName()] = make_timestamp($valuearray['year'],
-                                   $valuearray['month'],
-                                   $valuearray['day'],
-                                   0, 0, 0,
-                                   $this->_options['timezone'],
-                                   true);
+            // Get the calendar type used - see MDL-18375.
+            $calendartype = \core_calendar\type_factory::get_calendar_instance();
+            $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day']);
+            $value[$this->getName()] = make_timestamp($gregoriandate['year'],
+                                                      $gregoriandate['month'],
+                                                      $gregoriandate['day'],
+                                                      0, 0, 0,
+                                                      $this->_options['timezone'],
+                                                      true);
 
             return $value;
         } else {
index 0bc6a77..e3a908e 100644 (file)
@@ -39,9 +39,11 @@ require_once($CFG->libdir . '/formslib.php');
  * @copyright 2006 Jamie Pratt <me@jamiep.org>
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
+class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group {
+
     /**
-     * Options for the element
+     * Options for the element.
+     *
      * 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 +55,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.
@@ -76,8 +78,12 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
      * @param array $options Options to control the element's display
      * @param mixed $attributes Either a typical HTML attribute string or an associative array
      */
-    function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null)
-    {
+    function MoodleQuickForm_date_time_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
+        // Get the calendar type used - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+        $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(),
+                                'defaulttime' => 0, 'timezone' => 99, 'step' => 5, 'optional' => false);
+
         $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
         $this->_persistantFreeze = true;
         $this->_appendName = true;
@@ -94,7 +100,10 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
                 }
             }
         }
-        form_init_date_js();
+        // The YUI2 calendar only supports the gregorian calendar type.
+        if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') {
+            form_init_date_js();
+        }
     }
 
     /**
@@ -102,18 +111,14 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
      *
      * @access private
      */
-    function _createElements()
-    {
+    function _createElements() {
         global $OUTPUT;
 
-        $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");
-        }
-        for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) {
+        // Get the calendar type used - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+        $days = $calendartype->get_days();
+        $months = $calendartype->get_months();
+        for ($i = $this->_options['startyear']; $i <= $this->_options['stopyear']; $i++) {
             $years[$i] = $i;
         }
         for ($i=0; $i<=23; $i++) {
@@ -122,6 +127,8 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
         for ($i=0; $i<60; $i+=$this->_options['step']) {
             $minutes[$i] = sprintf("%02d",$i);
         }
+
+        $this->_elements = array();
         // E_STRICT creating elements without forms is nasty because it internally uses $this
         $this->_elements[] = @MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true);
         $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true);
@@ -133,10 +140,13 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
             $this->_elements[] = @MoodleQuickForm::createElement('select', 'hour', get_string('hour', 'form'), $hours, $this->getAttributes(), true);
             $this->_elements[] = @MoodleQuickForm::createElement('select', 'minute', get_string('minute', 'form'), $minutes, $this->getAttributes(), true);
         }
-        $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'),
-            array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs'));
+        // The YUI2 calendar only supports the gregorian calendar type so only display the calendar image if this is being used.
+        if (\core_calendar\type_factory::get_calendar_type() === 'gregorian') {
+            $this->_elements[] = @MoodleQuickForm::createElement('image', 'calendar', $OUTPUT->pix_url('i/calendar', 'moodle'),
+                array('title' => get_string('calendar', 'calendar'), 'class' => 'visibleifjs'));
+        }
         // If optional we add a checkbox which the user can use to turn if on
-        if($this->_options['optional']) {
+        if ($this->_options['optional']) {
             $this->_elements[] = @MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
         }
         foreach ($this->_elements as $element){
@@ -155,16 +165,15 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
      * @param object $caller calling object
      * @return bool
      */
-    function onQuickFormEvent($event, $arg, &$caller)
-    {
+    function onQuickFormEvent($event, $arg, &$caller) {
         switch ($event) {
             case 'updateValue':
-                // constant values override both default and submitted ones
-                // default values are overriden by submitted
+                // Constant values override both default and submitted ones
+                // default values are overriden by submitted.
                 $value = $this->_findValue($caller->_constantValues);
                 if (null === $value) {
-                    // if no boxes were checked, then there is no value in the array
-                    // yet we don't want to display default value in this case
+                    // If no boxes were checked, then there is no value in the array
+                    // yet we don't want to display default value in this case.
                     if ($caller->isSubmitted()) {
                         $value = $this->_findValue($caller->_submitValues);
                     } else {
@@ -179,7 +188,8 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
                     }
                 }
                 if (!is_array($value)) {
-                    $currentdate = usergetdate($value, $this->_options['timezone']);
+                    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+                    $currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']);
                     // Round minutes to the previous multiple of step.
                     $currentdate['minutes'] -= $currentdate['minutes'] % $this->_options['step'];
                     $value = array(
@@ -188,19 +198,19 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
                         'day' => $currentdate['mday'],
                         'month' => $currentdate['mon'],
                         'year' => $currentdate['year']);
-                    // If optional, default to off, unless a date was provided
-                    if($this->_options['optional']) {
+                    // If optional, default to off, unless a date was provided.
+                    if ($this->_options['optional']) {
                         $value['enabled'] = $requestvalue != 0;
                     }
                 } else {
                     $value['enabled'] = isset($value['enabled']);
                 }
-                if (null !== $value){
+                if (null !== $value) {
                     $this->setValue($value);
                 }
                 break;
             case 'createElement':
-                if($arg[2]['optional']) {
+                if ($arg[2]['optional']) {
                     // When using the function addElement, rather than createElement, we still
                     // enter this case, making this check necessary.
                     if ($this->_usedcreateelement) {
@@ -229,8 +239,7 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
      *
      * @return string
      */
-    function toHtml()
-    {
+    function toHtml() {
         include_once('HTML/QuickForm/Renderer/Default.php');
         $renderer = new HTML_QuickForm_Renderer_Default();
         $renderer->setElementTemplate('{element}');
@@ -254,8 +263,7 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
      * @param bool $required Whether a group is required
      * @param string $error An error message associated with a group
      */
-    function accept(&$renderer, $required = false, $error = null)
-    {
+    function accept(&$renderer, $required = false, $error = null) {
         $renderer->renderElement($this, $required, $error);
     }
 
@@ -266,8 +274,7 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
      * @param bool $assoc specifies if returned array is associative
      * @return array
      */
-    function exportValue(&$submitValues, $assoc = false)
-    {
+    function exportValue(&$submitValues, $assoc = false) {
         $value = null;
         $valuearray = array();
         foreach ($this->_elements as $element){
@@ -284,20 +291,24 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
                     return $value;
                 }
             }
-            $valuearray=$valuearray + array('year' => 1970, 'month' => 1, 'day' => 1, 'hour' => 0, 'minute' => 0);
-            $value[$this->getName()] = make_timestamp(
-                                   $valuearray['year'],
-                                   $valuearray['month'],
-                                   $valuearray['day'],
-                                   $valuearray['hour'],
-                                   $valuearray['minute'],
-                                   0,
-                                   $this->_options['timezone'],
-                                   true);
+            // Get the calendar type used - see MDL-18375.
+            $calendartype = \core_calendar\type_factory::get_calendar_instance();
+            $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'],
+                                                                 $valuearray['month'],
+                                                                 $valuearray['day'],
+                                                                 $valuearray['hour'],
+                                                                 $valuearray['minute']);
+            $value[$this->getName()] = make_timestamp($gregoriandate['year'],
+                                                      $gregoriandate['month'],
+                                                      $gregoriandate['day'],
+                                                      $gregoriandate['hour'],
+                                                      $gregoriandate['minute'],
+                                                      0,
+                                                      $this->_options['timezone'],
+                                                      true);
 
             return $value;
         } else {
-
             return null;
         }
     }
index a0fae10..ff068d4 100644 (file)
@@ -2132,24 +2132,14 @@ function format_time($totalsecs, $str = null) {
 }
 
 /**
- * Returns a formatted string that represents a date in user time
- *
- * Returns a formatted string that represents a date in user time
- * <b>WARNING: note that the format is for strftime(), not date().</b>
- * Because of a bug in most Windows time libraries, we can't use
- * the nicer %e, so we have to use %d which has leading zeroes.
- * A lot of the fuss in the function is just getting rid of these leading
- * zeroes as efficiently as possible.
- *
- * If parameter fixday = true (default), then take off leading
- * zero from %d, else maintain it.
+ * Returns a formatted string that represents a date in user time.
  *
  * @package core
  * @category time
  * @param int $date the timestamp in UTC, as obtained from the database.
  * @param string $format strftime format. You should probably get this using
  *        get_string('strftime...', 'langconfig');
- * @param int|float|string  $timezone by default, uses the user's time zone. if numeric and
+ * @param int|float|string $timezone by default, uses the user's time zone. if numeric and
  *        not 99 then daylight saving will not be added.
  *        {@link http://docs.moodle.org/dev/Time_API#Timezone}
  * @param bool $fixday If true (default) then the leading zero from %d is removed.
@@ -2158,71 +2148,8 @@ function format_time($totalsecs, $str = null) {
  * @return string the formatted date/time.
  */
 function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) {
-
-    global $CFG;
-
-    if (empty($format)) {
-        $format = get_string('strftimedaydatetime', 'langconfig');
-    }
-
-    if (!empty($CFG->nofixday)) {
-        // Config.php can force %d not to be fixed.
-        $fixday = false;
-    } else if ($fixday) {
-        $formatnoday = str_replace('%d', 'DD', $format);
-        $fixday = ($formatnoday != $format);
-        $format = $formatnoday;
-    }
-
-    // Note: This logic about fixing 12-hour time to remove unnecessary leading
-    // zero is required because on Windows, PHP strftime function does not
-    // support the correct 'hour without leading zero' parameter (%l).
-    if (!empty($CFG->nofixhour)) {
-        // Config.php can force %I not to be fixed.
-        $fixhour = false;
-    } else if ($fixhour) {
-        $formatnohour = str_replace('%I', 'HH', $format);
-        $fixhour = ($formatnohour != $format);
-        $format = $formatnohour;
-    }
-
-    // Add daylight saving offset for string timezones only, as we can't get dst for
-    // float values. if timezone is 99 (user default timezone), then try update dst.
-    if ((99 == $timezone) || !is_numeric($timezone)) {
-        $date += dst_offset_on($date, $timezone);
-    }
-
-    $timezone = get_user_timezone_offset($timezone);
-
-    // If we are running under Windows convert to windows encoding and then back to UTF-8
-    // (because it's impossible to specify UTF-8 to fetch locale info in Win32).
-
-    if (abs($timezone) > 13) {
-        // Server time.
-        $datestring = date_format_string($date, $format, $timezone);
-        if ($fixday) {
-            $daystring  = ltrim(str_replace(array(' 0', ' '), '', strftime(' %d', $date)));
-            $datestring = str_replace('DD', $daystring, $datestring);
-        }
-        if ($fixhour) {
-            $hourstring = ltrim(str_replace(array(' 0', ' '), '', strftime(' %I', $date)));
-            $datestring = str_replace('HH', $hourstring, $datestring);
-        }
-
-    } else {
-        $date += (int)($timezone * 3600);
-        $datestring = date_format_string($date, $format, $timezone);
-        if ($fixday) {
-            $daystring  = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %d', $date)));
-            $datestring = str_replace('DD', $daystring, $datestring);
-        }
-        if ($fixhour) {
-            $hourstring = ltrim(str_replace(array(' 0', ' '), '', gmstrftime(' %I', $date)));
-            $datestring = str_replace('HH', $hourstring, $datestring);
-        }
-    }
-
-    return $datestring;
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+    return $calendartype->timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour);
 }
 
 /**
@@ -2319,7 +2246,7 @@ function usergetdate($time, $timezone=99) {
     $getdate['wday'] = (int)$getdate['wday'];
     $getdate['mday'] = (int)$getdate['mday'];
     $getdate['hours'] = (int)$getdate['hours'];
-    $getdate['minutes']  = (int)$getdate['minutes'];
+    $getdate['minutes'] = (int)$getdate['minutes'];
     return $getdate;
 }
 
index 5df2fe1..cc8ae89 100644 (file)
@@ -652,6 +652,7 @@ class plugin_manager {
      * @return false|array array of standard plugins or false if the type is unknown
      */
     public static function standard_plugins_list($type) {
+
         $standard_plugins = array(
 
             'assignment' => array(
@@ -704,6 +705,10 @@ class plugin_manager {
                 'file', 'memcache', 'memcached', 'mongodb', 'session', 'static'
             ),
 
+            'calendartype' => array(
+                'gregorian'
+            ),
+
             'coursereport' => array(
                 //deprecated!
             ),
index 42489b1..32a4634 100644 (file)
@@ -262,6 +262,13 @@ 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);
 
+    // Multi-Calendar Support - see MDL-18375.
+    $calendartypes = \core_calendar\type_factory::get_list_of_calendar_types();
+    // We do not want to show this option unless there is more than one calendar type to display.
+    if (count($calendartypes) > 1) {
+        $mform->addElement('select', 'calendartype', get_string('preferredcalendar', 'calendar'), $calendartypes);
+    }
+
     if (!empty($CFG->allowuserthemes)) {
         $choices = array();
         $choices[''] = get_string('default');
index 5e45492..dfeb3e1 100644 (file)
@@ -1,59 +1,89 @@
 <?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/>.
 
 /**
- * Define datetime fields
+ * Define datetime fields.
  *
- * @author Mark Nelson <mark@moodle.com.au>
+ * @package profilefield_datetime
+ * @copyright 2010 Mark Nelson <markn@moodle.com>
  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
- * @version 20101022
  */
-
 class profile_define_datetime extends profile_define_base {
 
     /**
-     * Define the setting for a datetime custom field
+     * Define the setting for a datetime custom field.
      *
-     * @param object $form the user form
+     * @param moodleform $form the user form
      */
-    function define_form_specific($form) {
-        // Create variables to store start and end
-        $currentyear = date('Y');
-        $startyear = $currentyear - 100;
-        $endyear = $currentyear + 20;
+    public function define_form_specific($form) {
+        // Get the current calendar in use - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+
+        // Create variables to store start and end.
+        list($year, $month, $day) = explode('_', date('Y_m_d'));
+        $currentdate = $calendartype->convert_from_gregorian($year, $month, $day);
+        $currentyear = $currentdate['year'];
+        $startyear = $calendartype->get_min_year();
+        $endyear = $calendartype->get_max_year();
 
-        // Create array for the years
+        // Create array for the years.
         $arryears = array();
         for ($i = $startyear; $i <= $endyear; $i++) {
             $arryears[$i] = $i;
         }
 
-        // Add elements
+        // Add elements.
         $form->addElement('select', 'param1', get_string('startyear', 'profilefield_datetime'), $arryears);
         $form->setType('param1', PARAM_INT);
         $form->setDefault('param1', $currentyear);
 
         $form->addElement('select', 'param2', get_string('endyear', 'profilefield_datetime'), $arryears);
         $form->setType('param2', PARAM_INT);
-        $form->setDefault('param2', $currentyear + 20);
+        $form->setDefault('param2', $currentyear);
 
         $form->addElement('checkbox', 'param3', get_string('wanttime', 'profilefield_datetime'));
         $form->setType('param3', PARAM_INT);
 
+        $form->addElement('hidden', 'startday', '1');
+        $form->setType('startday', PARAM_INT);
+        $form->addElement('hidden', 'startmonth', '1');
+        $form->setType('startmonth', PARAM_INT);
+        $form->addElement('hidden', 'startyear', '1');
+        $form->setType('startyear', PARAM_INT);
+        $form->addElement('hidden', 'endday', '1');
+        $form->setType('endday', PARAM_INT);
+        $form->addElement('hidden', 'endmonth', '1');
+        $form->setType('endmonth', PARAM_INT);
+        $form->addElement('hidden', 'endyear', '1');
+        $form->setType('endyear', PARAM_INT);
         $form->addElement('hidden', 'defaultdata', '0');
         $form->setType('defaultdata', PARAM_INT);
     }
 
     /**
-     * Validate the data from the profile field form
+     * Validate the data from the profile field form.
      *
-     * @param   object   data from the add/edit profile field form
-     * @param   array    files
-     * @return  array    associative array of error messages
+     * @param stdClass $data from the add/edit profile field form
+     * @param array $files
+     * @return array associative array of error messages
      */
-    function define_validate_specific($data, $files) {
+    public function define_validate_specific($data, $files) {
         $errors = array();
 
-        // Make sure the start year is not greater than the end year
+        // Make sure the start year is not greater than the end year.
         if ($data->param1 > $data->param2) {
             $errors['param1'] = get_string('startyearafterend', 'profilefield_datetime');
         }
@@ -61,19 +91,86 @@ class profile_define_datetime extends profile_define_base {
         return $errors;
     }
 
+    /**
+     * Alter form based on submitted or existing data.
+     *
+     * @param moodleform $mform
+     */
+    public function define_after_data(&$mform) {
+        global $DB;
+
+        // If we are adding a new profile field then the dates have already been set
+        // by setDefault to the correct dates in the used calendar system. We only want
+        // to execute the rest of the code when we have the years in the DB saved in
+        // Gregorian that need converting to the date for this user.
+        $id = required_param('id', PARAM_INT);
+        if ($id === 0) {
+            return;
+        }
+
+        // Get the field data from the DB.
+        $field = $DB->get_record('user_info_field', array('id' => $id), 'param1, param2', MUST_EXIST);
+
+        // Get the current calendar in use - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+
+        // An array to store form values.
+        $values = array();
+
+        // The start and end year will be set as a Gregorian year in the DB. We want
+        // convert these to the equivalent year in the current calendar type being used.
+        $startdate = $calendartype->convert_from_gregorian($field->param1, 1, 1);
+        $values['startday'] = $startdate['day'];
+        $values['startmonth'] = $startdate['month'];
+        $values['startyear'] = $startdate['year'];
+        $values['param1'] = $startdate['year'];
+
+        $stopdate = $calendartype->convert_from_gregorian($field->param2, 1, 1);
+        $values['endday'] = $stopdate['day'];
+        $values['endmonth'] = $stopdate['month'];
+        $values['endyear'] = $stopdate['year'];
+        $values['param2'] = $stopdate['year'];
+
+        // Set the values.
+        foreach ($values as $key => $value) {
+            $param = $mform->getElement($key);
+            $param->setValue($value);
+        }
+    }
+
     /**
      * Preprocess data from the profile field form before
      * it is saved.
      *
-     * @param   object   data from the add/edit profile field form
-     * @return  object   processed data object
+     * @param stdClass $data from the add/edit profile field form
+     * @return stdClass processed data object
      */
-    function define_save_preprocess($data) {
+    public function define_save_preprocess($data) {
+        // Get the current calendar in use - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+
+        // Check if the start year was changed, if it was then convert from the start of that year.
+        if ($data->param1 != $data->startyear) {
+            $startdate = $calendartype->convert_to_gregorian($data->param1, 1, 1);
+        } else {
+            $startdate = $calendartype->convert_to_gregorian($data->param1, $data->startmonth, $data->startday);
+        }
+
+        // Check if the end year was changed, if it was then convert from the start of that year.
+        if ($data->param2 != $data->endyear) {
+            $stopdate = $calendartype->convert_to_gregorian($data->param2, 1, 1);
+        } else {
+            $stopdate = $calendartype->convert_to_gregorian($data->param2, $data->endmonth, $data->endday);
+        }
+
+        $data->param1 = $startdate['year'];
+        $data->param2 = $stopdate['year'];
+
         if (empty($data->param3)) {
-            $data->param3 = NULL;
+            $data->param3 = null;
         }
 
-        // No valid value in the default data column needed
+        // No valid value in the default data column needed.
         $data->defaultdata = '0';
 
         return $data;
index 17b0e3c..cbf506b 100644 (file)
@@ -1,35 +1,55 @@
 <?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/>.
 
 /**
- * Handles displaying and editing the datetime field
+ * Handles displaying and editing the datetime field.
  *
- * @author Mark Nelson <mark@moodle.com.au>
+ * @package profilefield_datetime
+ * @copyright 2010 Mark Nelson <markn@moodle.com>
  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
- * @version 20101022
  */
-
 class profile_field_datetime extends profile_field_base {
 
     /**
-     * Handles editing datetime fields
+     * Handles editing datetime fields.
      *
-     * @param object moodleform instance
+     * @param moodleform $mform
      */
-    function edit_field_add($mform) {
-        // Check if the field is required
+    public function edit_field_add($mform) {
+        // Get the current calendar in use - see MDL-18375.
+        $calendartype = \core_calendar\type_factory::get_calendar_instance();
+
+        // Check if the field is required.
         if ($this->field->required) {
             $optional = false;
         } else {
             $optional = true;
         }
 
+        // Convert the year stored in the DB as gregorian to that used by the calendar type.
+        $startdate = $calendartype->convert_from_gregorian($this->field->param1, 1, 1);
+        $stopdate = $calendartype->convert_from_gregorian($this->field->param2, 1, 1);
+
         $attributes = array(
-            'startyear' => $this->field->param1,
-            'stopyear'  => $this->field->param2,
+            'startyear' => $startdate['year'],
+            'stopyear'  => $stopdate['year'],
             'optional'  => $optional
         );
 
-        // Check if they wanted to include time as well
+        // Check if they wanted to include time as well.
         if (!empty($this->field->param3)) {
             $mform->addElement('date_time_selector', $this->inputname, format_string($this->field->name), $attributes);
         } else {
@@ -48,7 +68,7 @@ class profile_field_datetime extends profile_field_base {
      * @return int timestamp
      * @since Moodle 2.5
      */
-    function edit_save_data_preprocess($datetime, $datarecord) {
+    public function edit_save_data_preprocess($datetime, $datarecord) {
         // If timestamp then explode it to check if year is within field limit.
         $isstring = strpos($datetime, '-');
         if (empty($isstring)) {
@@ -66,17 +86,17 @@ class profile_field_datetime extends profile_field_base {
     }
 
     /**
-     * Display the data for this field
+     * Display the data for this field.
      */
-    function display_data() {
-        // Check if time was specified
+    public function display_data() {
+        // Check if time was specified.
         if (!empty($this->field->param3)) {
             $format = get_string('strftimedaydatetime', 'langconfig');
         } else {
             $format = get_string('strftimedate', 'langconfig');
         }
 
-        // Check if a date has been specified
+        // Check if a date has been specified.
         if (empty($this->data)) {
             return get_string('notset', 'profilefield_datetime');
         } else {
index 6127676..53ec7de 100644 (file)
@@ -1,11 +1,25 @@
 <?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/>.
 
 /**
- * The english language pack used in this profile field type
+ * The english language pack used in this profile field type.
  *
- * @author Mark Nelson - Pukunui Technology
+ * @package profilefield_datetime
+ * @copyright 2010 Mark Nelson <markn@moodle.com>
  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
- * @version 20101022
  */
 
 $string['currentdatedefault'] = 'Check to use current date as default';
index 1bb2ae0..9567c5e 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * @package    profilefield
- * @subpackage datetime
- * @copyright  2010 onwards Shane Elliot {@link http://pukunui.com}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * Version information for the datetime field.
+ *
+ * @package profilefield_datetime
+ * @copyright 2010 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  */
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013050100;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2013090200;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'profilefield_datetime'; // Full name of the plugin (used for diagnostics)
index ff7cbbc..e101961 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2013090500.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2013090500.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.