diff --git a/lang/en/course.php b/lang/en/course.php index a4e069df29f..4e43f8798fe 100644 --- a/lang/en/course.php +++ b/lang/en/course.php @@ -33,6 +33,10 @@ $string['activitychoosertabmode_desc'] = "The activity chooser enables a teacher $string['activitychoosertabmodeone'] = 'Starred, All, Activities, Resources, Recommended'; $string['activitychoosertabmodetwo'] = 'Starred, All, Recommended'; $string['activitychoosertabmodethree'] = 'Starred, Activities, Resources, Recommended'; +$string['activitydate:closed'] = 'Closed:'; +$string['activitydate:closes'] = 'Closes:'; +$string['activitydate:opened'] = 'Opened:'; +$string['activitydate:opens'] = 'Opens:'; $string['aria:coursecategory'] = 'Course category'; $string['aria:courseimage'] = 'Course image'; $string['aria:courseshortname'] = 'Course short name'; diff --git a/lib/classes/activity_dates.php b/lib/classes/activity_dates.php new file mode 100644 index 00000000000..74564e0f68d --- /dev/null +++ b/lib/classes/activity_dates.php @@ -0,0 +1,101 @@ +. + +/** + * Contains the base class for fetching the important dates in an activity module for a given module instance and a user. + * + * @package core + * @copyright Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +declare(strict_types=1); + +namespace core; + +use cm_info; + +/** + * Class for fetching the important dates of an activity module for a given module instance and a user. + * + * @copyright Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class activity_dates { + + /** + * @var cm_info The course module information object. + */ + protected $cm; + + /** + * @var int The user id. + */ + protected $userid; + + /** + * activity_dates constructor. + * + * @param cm_info $cm course module + * @param int $userid user id + */ + public function __construct(cm_info $cm, int $userid) { + $this->cm = $cm; + $this->userid = $userid; + } + + /** + * Returns a list of important dates in the given module for the user. + * + * @param cm_info $cm The course module information. + * @param int $userid The user ID. + * @return array|array[] + */ + public static function get_dates_for_module(cm_info $cm, int $userid): array { + $cmdatesclassname = static::get_dates_classname($cm->modname); + if (!$cmdatesclassname) { + return []; + } + + /** @var activity_dates $dates */ + $dates = new $cmdatesclassname($cm, $userid); + return $dates->get_dates(); + } + + /** + * Fetches the module's dates class implementation if it's available. + * + * @param string $modname The activity module name. Usually from cm_info::modname. + * @return string|null + */ + private static function get_dates_classname(string $modname): ?string { + $cmdatesclass = "mod_{$modname}\\dates"; + if (class_exists($cmdatesclass) && is_subclass_of($cmdatesclass, self::class)) { + return $cmdatesclass; + } + + return null; + } + + /** + * Returns a list of important dates for this module. + * + * @return array[] Each element of the array is an array with keys: + * label - The label for the date + * timestamp - The date + */ + protected abstract function get_dates(): array; +} diff --git a/mod/choice/classes/dates.php b/mod/choice/classes/dates.php new file mode 100644 index 00000000000..ede2d4ffcbb --- /dev/null +++ b/mod/choice/classes/dates.php @@ -0,0 +1,68 @@ +. + +/** + * Contains the class for fetching the important dates in mod_choice for a given module instance and a user. + * + * @package mod_choice + * @copyright Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +declare(strict_types=1); + +namespace mod_choice; + +use core\activity_dates; + +/** + * Class for fetching the important dates in mod_choice for a given module instance and a user. + * + * @copyright Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class dates extends activity_dates { + + /** + * Returns a list of important dates in mod_choice + * + * @return array + */ + protected function get_dates(): array { + $timeopen = $this->cm->customdata['timeopen'] ?? null; + $timeclose = $this->cm->customdata['timeclose'] ?? null; + $now = time(); + $dates = []; + + if ($timeopen) { + $openlabelid = $timeopen > $now ? 'activitydate:opens' : 'activitydate:opened'; + $dates[] = [ + 'label' => get_string($openlabelid, 'course'), + 'timestamp' => (int) $timeopen, + ]; + } + + if ($timeclose) { + $closelabelid = $timeclose > $now ? 'activitydate:closes' : 'activitydate:closed'; + $dates[] = [ + 'label' => get_string($closelabelid, 'course'), + 'timestamp' => (int) $timeclose, + ]; + } + + return $dates; + } +} diff --git a/mod/choice/tests/dates_test.php b/mod/choice/tests/dates_test.php new file mode 100644 index 00000000000..0f0624a27b9 --- /dev/null +++ b/mod/choice/tests/dates_test.php @@ -0,0 +1,122 @@ +. + +/** + * Contains unit tests for mod_choice\dates. + * + * @package mod_choice + * @category test + * @copyright Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +declare(strict_types=1); + +namespace mod_choice; + +use advanced_testcase; +use cm_info; +use core\activity_dates; + +/** + * Class for unit testing mod_choice\dates. + * + * @copyright Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class dates_testcase extends advanced_testcase { + + /** + * Data provider for get_dates_for_module(). + * @return array[] + */ + public function get_dates_for_module_provider(): array { + $now = time(); + $before = $now - DAYSECS; + $earlier = $before - DAYSECS; + $after = $now + DAYSECS; + $later = $after + DAYSECS; + + return [ + 'without any dates' => [ + null, null, [] + ], + 'only with opening time' => [ + $after, null, [ + ['label' => 'Opens:', 'timestamp' => $after], + ] + ], + 'only with closing time' => [ + null, $after, [ + ['label' => 'Closes:', 'timestamp' => $after], + ] + ], + 'with both times' => [ + $after, $later, [ + ['label' => 'Opens:', 'timestamp' => $after], + ['label' => 'Closes:', 'timestamp' => $later], + ] + ], + 'between the dates' => [ + $before, $after, [ + ['label' => 'Opened:', 'timestamp' => $before], + ['label' => 'Closes:', 'timestamp' => $after], + ] + ], + 'dates are past' => [ + $earlier, $before, [ + ['label' => 'Opened:', 'timestamp' => $earlier], + ['label' => 'Closed:', 'timestamp' => $before], + ] + ], + ]; + } + + /** + * Test for get_dates_for_module(). + * + * @dataProvider get_dates_for_module_provider + * @param int|null $timeopen Time of opening the choice + * @param int|null $timeclose Time of closing the choice + * @param array $expected The expected value of calling get_dates_for_module() + */ + public function test_get_dates_for_module(?int $timeopen, ?int $timeclose, array $expected): void { + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $user = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($user->id, $course->id); + + $data = ['course' => $course->id]; + if ($timeopen) { + $data['timeopen'] = $timeopen; + } + if ($timeclose) { + $data['timeclose'] = $timeclose; + } + $choice = $this->getDataGenerator()->create_module('choice', $data); + + $this->setUser($user); + + $cm = get_coursemodule_from_instance('choice', $choice->id); + // Make sure we're using a cm_info object. + $cm = cm_info::create($cm); + + $dates = activity_dates::get_dates_for_module($cm, (int)$user->id); + + $this->assertEquals($expected, $dates); + } +}