├── tests └── behat │ └── installed.feature ├── pix └── icon.svg ├── db ├── uninstall.php ├── install.php ├── upgrade.php ├── install.xml └── access.php ├── locallib.php ├── version.php ├── classes ├── event │ ├── course_module_instance_list_viewed.php │ └── course_module_viewed.php ├── group.php └── main.php ├── grade.php ├── lang └── en │ └── groupalloc.php ├── backup └── moodle2 │ ├── backup_groupalloc_stepslib.php │ ├── backup_groupalloc_activity_task.class.php │ ├── restore_groupalloc_stepslib.php │ └── restore_groupalloc_activity_task.class.php ├── index.php ├── view.php ├── mod_form.php └── lib.php /tests/behat/installed.feature: -------------------------------------------------------------------------------- 1 | @mod @mod_groupalloc 2 | Feature: Installation succeeds 3 | In order to use this plugin 4 | As a user 5 | I need the installation to work 6 | 7 | Scenario: Check the Plugins overview for the name of this plugin 8 | Given I log in as "admin" 9 | And I navigate to "Plugins overview" node in "Site administration > Plugins" 10 | Then the following should exist in the "plugins-control-panel" table: 11 | |Plugin name| 12 | |mod_groupalloc| 13 | -------------------------------------------------------------------------------- /pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /db/uninstall.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Provides code to be executed during the module uninstallation 19 | * 20 | * @see uninstall_plugin() 21 | * 22 | * @package mod_groupalloc 23 | * @copyright 2017 Marina Glancy 24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 | */ 26 | 27 | /** 28 | * Custom uninstallation procedure 29 | */ 30 | function xmldb_groupalloc_uninstall() { 31 | return true; 32 | } 33 | -------------------------------------------------------------------------------- /locallib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Internal library of functions for module groupalloc 19 | * 20 | * All the groupalloc specific functions, needed to implement the module 21 | * logic, should go here. Never include this file from your lib.php! 22 | * 23 | * @package mod_groupalloc 24 | * @copyright 2017 Marina Glancy 25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 | */ 27 | 28 | defined('MOODLE_INTERNAL') || die(); 29 | 30 | /* 31 | * Does something really useful with the passed things 32 | * 33 | * @param array $things 34 | * @return object 35 | *function groupalloc_do_something_useful(array $things) { 36 | * return new stdClass(); 37 | *} 38 | */ 39 | -------------------------------------------------------------------------------- /version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Defines the version and other meta-info about the plugin 19 | * 20 | * Setting the $plugin->version to 0 prevents the plugin from being installed. 21 | * See https://docs.moodle.org/dev/version.php for more info. 22 | * 23 | * @package mod_groupalloc 24 | * @copyright 2017 Marina Glancy 25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 | */ 27 | 28 | defined('MOODLE_INTERNAL') || die(); 29 | 30 | $plugin->component = 'mod_groupalloc'; 31 | $plugin->version = 2017012900; 32 | $plugin->release = 'v1.0'; 33 | $plugin->requires = 2016120500; 34 | $plugin->maturity = MATURITY_ALPHA; 35 | $plugin->cron = 0; 36 | $plugin->dependencies = array(); 37 | -------------------------------------------------------------------------------- /classes/event/course_module_instance_list_viewed.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * The mod_groupalloc instance list viewed event. 19 | * 20 | * @package mod_groupalloc 21 | * @copyright 2017 Marina Glancy 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace mod_groupalloc\event; 26 | 27 | defined('MOODLE_INTERNAL') || die(); 28 | 29 | /** 30 | * The mod_groupalloc instance list viewed event class. 31 | * 32 | * @package mod_groupalloc 33 | * @copyright 2017 Marina Glancy 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed { 37 | } 38 | -------------------------------------------------------------------------------- /grade.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Redirect the user to the appropriate submission related page 19 | * 20 | * @package mod_groupalloc 21 | * @category grade 22 | * @copyright 2017 Marina Glancy 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | require_once(__DIR__ . "../../../config.php"); 27 | 28 | $id = required_param('id', PARAM_INT);// Course module ID. 29 | // Item number may be != 0 for activities that allow more than one grade per user. 30 | $itemnumber = optional_param('itemnumber', 0, PARAM_INT); 31 | $userid = optional_param('userid', 0, PARAM_INT); // Graded user ID (optional). 32 | 33 | // In the simplest case just redirect to the view page. 34 | redirect('view.php?id='.$id); 35 | -------------------------------------------------------------------------------- /db/install.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Provides code to be executed during the module installation 19 | * 20 | * This file replaces the legacy STATEMENTS section in db/install.xml, 21 | * lib.php/modulename_install() post installation hook and partially defaults.php. 22 | * 23 | * @package mod_groupalloc 24 | * @copyright 2017 Marina Glancy 25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 | */ 27 | 28 | /** 29 | * Post installation procedure 30 | * 31 | * @see upgrade_plugins_modules() 32 | */ 33 | function xmldb_groupalloc_install() { 34 | } 35 | 36 | /** 37 | * Post installation recovery procedure 38 | * 39 | * @see upgrade_plugins_modules() 40 | */ 41 | function xmldb_groupalloc_install_recovery() { 42 | } 43 | -------------------------------------------------------------------------------- /db/upgrade.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file keeps track of upgrades to the groupalloc module 19 | * 20 | * Sometimes, changes between versions involve alterations to database 21 | * structures and other major things that may break installations. The upgrade 22 | * function in this file will attempt to perform all the necessary actions to 23 | * upgrade your older installation to the current version. If there's something 24 | * it cannot do itself, it will tell you what you need to do. The commands in 25 | * here will all be database-neutral, using the functions defined in DLL libraries. 26 | * 27 | * @package mod_groupalloc 28 | * @copyright 2017 Marina Glancy 29 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 | */ 31 | 32 | defined('MOODLE_INTERNAL') || die(); 33 | 34 | /** 35 | * Execute groupalloc upgrade from the given old version 36 | * 37 | * @param int $oldversion 38 | * @return bool 39 | */ 40 | function xmldb_groupalloc_upgrade($oldversion) { 41 | global $DB; 42 | 43 | $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes. 44 | 45 | return true; 46 | } 47 | -------------------------------------------------------------------------------- /lang/en/groupalloc.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | 18 | /** 19 | * English strings for groupalloc 20 | * 21 | * You can have a rather longer description of the file as well, 22 | * if you like, and it can span multiple lines. 23 | * 24 | * @package mod_groupalloc 25 | * @copyright 2017 Marina Glancy 26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 | */ 28 | 29 | defined('MOODLE_INTERNAL') || die(); 30 | 31 | $string['modulename'] = 'Group allocation'; 32 | $string['modulenameplural'] = 'Group allocations'; 33 | $string['modulename_help'] = 'Use the Group allocation module to allow students to allocate themselves to the groups'; 34 | $string['groupalloc:addinstance'] = 'Add a new group allocation'; 35 | $string['groupalloc:joingroup'] = 'Join a group'; 36 | $string['groupalloc:creategroup'] = 'Create new groups'; 37 | $string['groupalloc:createpasswordgroup'] = 'Create password-protected groups'; 38 | $string['groupalloc:leavegroup'] = 'Leave a group'; 39 | $string['groupalloc:view'] = 'View group allocation activity'; 40 | $string['groupalloc:viewmembers'] = 'View members of groups'; 41 | $string['groupallocname'] = 'Name'; 42 | $string['pluginadministration'] = 'Group allocation administration'; 43 | $string['pluginname'] = 'Group allocation'; 44 | -------------------------------------------------------------------------------- /classes/event/course_module_viewed.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Defines the view event. 19 | * 20 | * @package mod_groupalloc 21 | * @copyright 2017 Marina Glancy 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace mod_groupalloc\event; 26 | 27 | defined('MOODLE_INTERNAL') || die(); 28 | 29 | /** 30 | * The mod_groupalloc instance viewed event class 31 | * 32 | * If the view mode needs to be stored as well, you may need to 33 | * override methods get_url() and get_legacy_log_data(), too. 34 | * 35 | * @package mod_groupalloc 36 | * @copyright 2017 Marina Glancy 37 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 | */ 39 | class course_module_viewed extends \core\event\course_module_viewed { 40 | 41 | /** 42 | * Initialize the event 43 | */ 44 | protected function init() { 45 | $this->data['objecttable'] = 'groupalloc'; 46 | parent::init(); 47 | } 48 | 49 | public static function create_from_cm(\cm_info $cm, $course, $record) { 50 | $event = self::create(array( 51 | 'objectid' => $cm->instance, 52 | 'context' => $cm->context 53 | )); 54 | $event->add_record_snapshot('course_modules', $cm); 55 | $event->add_record_snapshot('course', $course); 56 | $event->add_record_snapshot($cm->modname, $record); 57 | return $event; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /classes/group.php: -------------------------------------------------------------------------------- 1 | main = $main; 11 | if (is_object($group)) { 12 | $this->group = $group; 13 | $this->groupid = $group->id; 14 | } else { 15 | $this->groupid = $group; 16 | } 17 | } 18 | 19 | protected function retrieve() { 20 | global $DB; 21 | if ($this->group === null) { 22 | $this->group = $DB->get_record('groups', ['id' => $this->groupid]); 23 | } 24 | } 25 | 26 | public function get_formatted_name() { 27 | $this->retrieve(); 28 | $coursecontext = $this->main->get_cm()->context->get_course_context(); 29 | return format_string($this->group->name, true, $coursecontext); 30 | } 31 | 32 | public function get_id() { 33 | return $this->groupid; 34 | } 35 | 36 | public function get_members() { 37 | global $CFG; 38 | require_once($CFG->dirroot.'/group/lib.php'); 39 | if ($this->members === null) { 40 | $this->members = groups_get_members($this->groupid, user_picture::fields('u')); 41 | } 42 | return $this->members; 43 | } 44 | 45 | public function is_member($user = null) { 46 | global $USER; 47 | $user = $user ?: $USER; 48 | $members = $this->get_members(); 49 | return array_key_exists($user->id, $members); 50 | } 51 | 52 | public function add_member($user) { 53 | global $CFG; 54 | require_once($CFG->dirroot.'/group/lib.php'); 55 | $this->get_members(); 56 | if (!array_key_exists($user->id, $this->members)) { 57 | groups_add_member($this->groupid, $user); 58 | $this->members[$user->id] = $user; 59 | } 60 | } 61 | 62 | public function remove_member($user) { 63 | global $CFG; 64 | require_once($CFG->dirroot.'/group/lib.php'); 65 | $this->get_members(); 66 | if (array_key_exists($user->id, $this->members)) { 67 | groups_remove_member($this->groupid, $user); 68 | unset($this->members[$user->id]); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /backup/moodle2/backup_groupalloc_stepslib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Define all the backup steps that will be used by the backup_groupalloc_activity_task 19 | * 20 | * @package mod_groupalloc 21 | * @category backup 22 | * @copyright 2017 Marina Glancy 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die; 27 | 28 | /** 29 | * Define the complete groupalloc structure for backup, with file and id annotations 30 | * 31 | * @package mod_groupalloc 32 | * @category backup 33 | * @copyright 2017 Marina Glancy 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class backup_groupalloc_activity_structure_step extends backup_activity_structure_step { 37 | 38 | /** 39 | * Defines the backup structure of the module 40 | * 41 | * @return backup_nested_element 42 | */ 43 | protected function define_structure() { 44 | 45 | // Get know if we are including userinfo. 46 | $userinfo = $this->get_setting_value('userinfo'); 47 | 48 | // Define the root element describing the groupalloc instance. 49 | $groupalloc = new backup_nested_element('groupalloc', array('id'), array( 50 | 'name', 'intro', 'introformat', 'grade')); 51 | 52 | // If we had more elements, we would build the tree here. 53 | 54 | // Define data sources. 55 | $groupalloc->set_source_table('groupalloc', array('id' => backup::VAR_ACTIVITYID)); 56 | 57 | // If we were referring to other tables, we would annotate the relation 58 | // with the element's annotate_ids() method. 59 | 60 | // Define file annotations (we do not use itemid in this example). 61 | $groupalloc->annotate_files('mod_groupalloc', 'intro', null); 62 | 63 | // Return the root element (groupalloc), wrapped into standard activity structure. 64 | return $this->prepare_activity_structure($groupalloc); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /backup/moodle2/backup_groupalloc_activity_task.class.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Defines backup_groupalloc_activity_task class 19 | * 20 | * @package mod_groupalloc 21 | * @category backup 22 | * @copyright 2017 Marina Glancy 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die; 27 | 28 | require_once($CFG->dirroot . '/mod/groupalloc/backup/moodle2/backup_groupalloc_stepslib.php'); 29 | 30 | /** 31 | * Provides the steps to perform one complete backup of the groupalloc instance 32 | * 33 | * @package mod_groupalloc 34 | * @category backup 35 | * @copyright 2017 Marina Glancy 36 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 | */ 38 | class backup_groupalloc_activity_task extends backup_activity_task { 39 | 40 | /** 41 | * No specific settings for this activity 42 | */ 43 | protected function define_my_settings() { 44 | } 45 | 46 | /** 47 | * Defines a backup step to store the instance data in the groupalloc.xml file 48 | */ 49 | protected function define_my_steps() { 50 | $this->add_step(new backup_groupalloc_activity_structure_step('groupalloc_structure', 'groupalloc.xml')); 51 | } 52 | 53 | /** 54 | * Encodes URLs to the index.php and view.php scripts 55 | * 56 | * @param string $content some HTML text that eventually contains URLs to the activity instance scripts 57 | * @return string the content with the URLs encoded 58 | */ 59 | static public function encode_content_links($content) { 60 | global $CFG; 61 | 62 | $base = preg_quote($CFG->wwwroot, '/'); 63 | 64 | // Link to the list of groupallocs. 65 | $search = '/('.$base.'\/mod\/groupalloc\/index.php\?id\=)([0-9]+)/'; 66 | $content = preg_replace($search, '$@GROUPALLOCINDEX*$2@$', $content); 67 | 68 | // Link to groupalloc view by moduleid. 69 | $search = '/('.$base.'\/mod\/groupalloc\/view.php\?id\=)([0-9]+)/'; 70 | $content = preg_replace($search, '$@GROUPALLOCVIEWBYID*$2@$', $content); 71 | 72 | return $content; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /backup/moodle2/restore_groupalloc_stepslib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Define all the restore steps that will be used by the restore_groupalloc_activity_task 19 | * 20 | * @package mod_groupalloc 21 | * @category backup 22 | * @copyright 2017 Marina Glancy 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | /** 27 | * Structure step to restore one groupalloc activity 28 | * 29 | * @package mod_groupalloc 30 | * @category backup 31 | * @copyright 2017 Marina Glancy 32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 | */ 34 | class restore_groupalloc_activity_structure_step extends restore_activity_structure_step { 35 | 36 | /** 37 | * Defines structure of path elements to be processed during the restore 38 | * 39 | * @return array of {@link restore_path_element} 40 | */ 41 | protected function define_structure() { 42 | 43 | $paths = array(); 44 | $paths[] = new restore_path_element('groupalloc', '/activity/groupalloc'); 45 | 46 | // Return the paths wrapped into standard activity structure. 47 | return $this->prepare_activity_structure($paths); 48 | } 49 | 50 | /** 51 | * Process the given restore path element data 52 | * 53 | * @param array $data parsed element data 54 | */ 55 | protected function process_groupalloc($data) { 56 | global $DB; 57 | 58 | $data = (object)$data; 59 | $oldid = $data->id; 60 | $data->course = $this->get_courseid(); 61 | 62 | if (empty($data->timecreated)) { 63 | $data->timecreated = time(); 64 | } 65 | 66 | if (empty($data->timemodified)) { 67 | $data->timemodified = time(); 68 | } 69 | 70 | if ($data->grade < 0) { 71 | // Scale found, get mapping. 72 | $data->grade = -($this->get_mappingid('scale', abs($data->grade))); 73 | } 74 | 75 | // Create the groupalloc instance. 76 | $newitemid = $DB->insert_record('groupalloc', $data); 77 | $this->apply_activity_instance($newitemid); 78 | } 79 | 80 | /** 81 | * Post-execution actions 82 | */ 83 | protected function after_execute() { 84 | // Add groupalloc related files, no need to match by itemname (just internally handled context). 85 | $this->add_related_files('mod_groupalloc', 'intro', null); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /db/install.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
-------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This is a one-line short description of the file 19 | * 20 | * You can have a rather longer description of the file as well, 21 | * if you like, and it can span multiple lines. 22 | * 23 | * @package mod_groupalloc 24 | * @copyright 2017 Marina Glancy 25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 | */ 27 | 28 | // Replace groupalloc with the name of your module and remove this line. 29 | 30 | require_once(dirname(dirname(dirname(__FILE__))).'/config.php'); 31 | require_once(dirname(__FILE__).'/lib.php'); 32 | 33 | $id = required_param('id', PARAM_INT); // Course. 34 | 35 | $course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST); 36 | 37 | require_course_login($course); 38 | 39 | $params = array( 40 | 'context' => context_course::instance($course->id) 41 | ); 42 | $event = \mod_groupalloc\event\course_module_instance_list_viewed::create($params); 43 | $event->add_record_snapshot('course', $course); 44 | $event->trigger(); 45 | 46 | $strname = get_string('modulenameplural', 'mod_groupalloc'); 47 | $PAGE->set_url('/mod/groupalloc/index.php', array('id' => $id)); 48 | $PAGE->navbar->add($strname); 49 | $PAGE->set_title("$course->shortname: $strname"); 50 | $PAGE->set_heading($course->fullname); 51 | $PAGE->set_pagelayout('incourse'); 52 | 53 | echo $OUTPUT->header(); 54 | echo $OUTPUT->heading($strname); 55 | 56 | if (! $groupallocs = get_all_instances_in_course('groupalloc', $course)) { 57 | notice(get_string('nogroupallocs', 'groupalloc'), new moodle_url('/course/view.php', array('id' => $course->id))); 58 | } 59 | 60 | $usesections = course_format_uses_sections($course->format); 61 | 62 | $table = new html_table(); 63 | $table->attributes['class'] = 'generaltable mod_index'; 64 | 65 | if ($usesections) { 66 | $strsectionname = get_string('sectionname', 'format_'.$course->format); 67 | $table->head = array ($strsectionname, $strname); 68 | $table->align = array ('center', 'left'); 69 | } else { 70 | $table->head = array ($strname); 71 | $table->align = array ('left'); 72 | } 73 | 74 | $modinfo = get_fast_modinfo($course); 75 | $currentsection = ''; 76 | foreach ($modinfo->instances['groupalloc'] as $cm) { 77 | $row = array(); 78 | if ($usesections) { 79 | if ($cm->sectionnum !== $currentsection) { 80 | if ($cm->sectionnum) { 81 | $row[] = get_section_name($course, $cm->sectionnum); 82 | } 83 | if ($currentsection !== '') { 84 | $table->data[] = 'hr'; 85 | } 86 | $currentsection = $cm->sectionnum; 87 | } 88 | } 89 | 90 | $class = $cm->visible ? null : array('class' => 'dimmed'); 91 | 92 | $row[] = html_writer::link(new moodle_url('view.php', array('id' => $cm->id)), 93 | $cm->get_formatted_name(), $class); 94 | $table->data[] = $row; 95 | } 96 | 97 | echo html_writer::table($table); 98 | 99 | echo $OUTPUT->footer(); 100 | -------------------------------------------------------------------------------- /db/access.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Capability definitions for the groupalloc module 19 | * 20 | * The capabilities are loaded into the database table when the module is 21 | * installed or updated. Whenever the capability definitions are updated, 22 | * the module version number should be bumped up. 23 | * 24 | * The system has four possible values for a capability: 25 | * CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT, and inherit (not set). 26 | * 27 | * It is important that capability names are unique. The naming convention 28 | * for capabilities that are specific to modules and blocks is as follows: 29 | * [mod/block]/: 30 | * 31 | * component_name should be the same as the directory name of the mod or block. 32 | * 33 | * Core moodle capabilities are defined thus: 34 | * moodle/: 35 | * 36 | * Examples: mod/forum:viewpost 37 | * block/recent_activity:view 38 | * moodle/site:deleteuser 39 | * 40 | * The variable name for the capability definitions array is $capabilities 41 | * 42 | * @package mod_groupalloc 43 | * @copyright 2017 Marina Glancy 44 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 45 | */ 46 | 47 | defined('MOODLE_INTERNAL') || die(); 48 | 49 | $capabilities = array( 50 | 'mod/groupalloc:addinstance' => array( 51 | 'riskbitmask' => RISK_XSS, 52 | 'captype' => 'write', 53 | 'contextlevel' => CONTEXT_COURSE, 54 | 'archetypes' => array( 55 | 'editingteacher' => CAP_ALLOW, 56 | 'manager' => CAP_ALLOW 57 | ), 58 | 'clonepermissionsfrom' => 'moodle/course:manageactivities' 59 | ), 60 | 61 | 'mod/groupalloc:view' => array( 62 | 'captype' => 'read', 63 | 'contextlevel' => CONTEXT_MODULE, 64 | 'archetypes' => array( 65 | 'guest' => CAP_ALLOW, 66 | 'user' => CAP_ALLOW, 67 | ) 68 | ), 69 | 70 | 'mod/groupalloc:joingroup' => array( 71 | 'captype' => 'write', 72 | 'contextlevel' => CONTEXT_MODULE, 73 | 'archetypes' => array( 74 | 'student' => CAP_ALLOW, 75 | 'teacher' => CAP_ALLOW, 76 | 'editingteacher' => CAP_ALLOW, 77 | 'frontpage' => CAP_ALLOW, 78 | ) 79 | ), 80 | 81 | 'mod/groupalloc:leavegroup' => array( 82 | 'captype' => 'write', 83 | 'contextlevel' => CONTEXT_MODULE, 84 | 'archetypes' => array( 85 | 'student' => CAP_ALLOW, 86 | 'teacher' => CAP_ALLOW, 87 | 'editingteacher' => CAP_ALLOW, 88 | 'frontpage' => CAP_ALLOW, 89 | ) 90 | ), 91 | 92 | 'mod/groupalloc:viewmembers' => array( 93 | 'captype' => 'write', 94 | 'contextlevel' => CONTEXT_MODULE, 95 | 'archetypes' => array( 96 | 'student' => CAP_ALLOW, 97 | 'teacher' => CAP_ALLOW, 98 | 'editingteacher' => CAP_ALLOW, 99 | 'frontpage' => CAP_ALLOW, 100 | ) 101 | ), 102 | 103 | 'mod/groupalloc:creategroup' => array( 104 | 'riskbitmask' => RISK_SPAM, 105 | 'captype' => 'write', 106 | 'contextlevel' => CONTEXT_MODULE, 107 | ), 108 | 109 | 'mod/groupalloc:createpasswordgroup' => array( 110 | 'riskbitmask' => RISK_SPAM, 111 | 'captype' => 'write', 112 | 'contextlevel' => CONTEXT_MODULE, 113 | 'archetypes' => array( 114 | 'editingteacher' => CAP_ALLOW, 115 | 'manager' => CAP_ALLOW 116 | ), 117 | 'clonepermissionsfrom' => 'moodle/course:managegroups' 118 | ), 119 | ); 120 | -------------------------------------------------------------------------------- /backup/moodle2/restore_groupalloc_activity_task.class.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Provides the restore activity task class 19 | * 20 | * @package mod_groupalloc 21 | * @category backup 22 | * @copyright 2017 Marina Glancy 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die(); 27 | 28 | require_once($CFG->dirroot . '/mod/groupalloc/backup/moodle2/restore_groupalloc_stepslib.php'); 29 | 30 | /** 31 | * Restore task for the groupalloc activity module 32 | * 33 | * Provides all the settings and steps to perform complete restore of the activity. 34 | * 35 | * @package mod_groupalloc 36 | * @category backup 37 | * @copyright 2017 Marina Glancy 38 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 | */ 40 | class restore_groupalloc_activity_task extends restore_activity_task { 41 | 42 | /** 43 | * Define (add) particular settings this activity can have 44 | */ 45 | protected function define_my_settings() { 46 | // No particular settings for this activity. 47 | } 48 | 49 | /** 50 | * Define (add) particular steps this activity can have 51 | */ 52 | protected function define_my_steps() { 53 | // We have just one structure step here. 54 | $this->add_step(new restore_groupalloc_activity_structure_step('groupalloc_structure', 'groupalloc.xml')); 55 | } 56 | 57 | /** 58 | * Define the contents in the activity that must be 59 | * processed by the link decoder 60 | */ 61 | static public function define_decode_contents() { 62 | $contents = array(); 63 | 64 | $contents[] = new restore_decode_content('groupalloc', array('intro'), 'groupalloc'); 65 | 66 | return $contents; 67 | } 68 | 69 | /** 70 | * Define the decoding rules for links belonging 71 | * to the activity to be executed by the link decoder 72 | */ 73 | static public function define_decode_rules() { 74 | $rules = array(); 75 | 76 | $rules[] = new restore_decode_rule('GROUPALLOCVIEWBYID', '/mod/groupalloc/view.php?id=$1', 'course_module'); 77 | $rules[] = new restore_decode_rule('GROUPALLOCINDEX', '/mod/groupalloc/index.php?id=$1', 'course'); 78 | 79 | return $rules; 80 | 81 | } 82 | 83 | /** 84 | * Define the restore log rules that will be applied 85 | * by the {@link restore_logs_processor} when restoring 86 | * groupalloc logs. It must return one array 87 | * of {@link restore_log_rule} objects 88 | */ 89 | static public function define_restore_log_rules() { 90 | $rules = array(); 91 | 92 | $rules[] = new restore_log_rule('groupalloc', 'add', 'view.php?id={course_module}', '{groupalloc}'); 93 | $rules[] = new restore_log_rule('groupalloc', 'update', 'view.php?id={course_module}', '{groupalloc}'); 94 | $rules[] = new restore_log_rule('groupalloc', 'view', 'view.php?id={course_module}', '{groupalloc}'); 95 | 96 | return $rules; 97 | } 98 | 99 | /** 100 | * Define the restore log rules that will be applied 101 | * by the {@link restore_logs_processor} when restoring 102 | * course logs. It must return one array 103 | * of {@link restore_log_rule} objects 104 | * 105 | * Note this rules are applied when restoring course logs 106 | * by the restore final task, but are defined here at 107 | * activity level. All them are rules not linked to any module instance (cmid = 0) 108 | */ 109 | static public function define_restore_log_rules_for_course() { 110 | $rules = array(); 111 | 112 | $rules[] = new restore_log_rule('groupalloc', 'view all', 'index.php?id={course}', null); 113 | 114 | return $rules; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /view.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Prints a particular instance of groupalloc 19 | * 20 | * You can have a rather longer description of the file as well, 21 | * if you like, and it can span multiple lines. 22 | * 23 | * @package mod_groupalloc 24 | * @copyright 2017 Marina Glancy 25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 | */ 27 | 28 | // Replace groupalloc with the name of your module and remove this line. 29 | 30 | require_once(dirname(dirname(dirname(__FILE__))).'/config.php'); 31 | require_once(dirname(__FILE__).'/lib.php'); 32 | 33 | $groupallocid = optional_param('g', 0, PARAM_INT); // Groupalloc instance ID - it should be named as the first character of the module. 34 | if ($groupallocid) { 35 | list($course, $cm) = get_course_and_cm_from_instance($groupallocid, 'groupalloc'); 36 | } else { 37 | $cmid = required_param('id', PARAM_INT); // Course_module ID. 38 | list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'groupalloc'); 39 | } 40 | 41 | require_login($course, true, $cm); 42 | 43 | $groupalloc = $PAGE->activityrecord; 44 | 45 | \mod_groupalloc\event\course_module_viewed::create_from_cm($cm, $course, $groupalloc)->trigger(); 46 | 47 | // Print the page header. 48 | 49 | $PAGE->set_url('/mod/groupalloc/view.php', array('id' => $cm->id)); 50 | $PAGE->set_title(format_string($groupalloc->name)); 51 | $PAGE->set_heading(format_string($course->fullname)); 52 | 53 | /* 54 | * Other things you may want to set - remove if not needed. 55 | * $PAGE->set_cacheable(false); 56 | * $PAGE->set_focuscontrol('some-html-id'); 57 | * $PAGE->add_body_class('groupalloc-'.$somevar); 58 | */ 59 | 60 | $main = new mod_groupalloc_main($cm, $groupalloc); 61 | $main->process_nonjs_actions(); 62 | 63 | // Output starts here. 64 | echo $OUTPUT->header(); 65 | 66 | // Conditions to show the intro can change to look for own settings or whatever. 67 | if ($groupalloc->intro) { 68 | echo $OUTPUT->box(format_module_intro('groupalloc', $groupalloc, $cm->id), 'generalbox mod_introbox', 'groupallocintro'); 69 | } 70 | 71 | // Replace the following lines with you own code. 72 | echo $OUTPUT->heading(format_string($groupalloc->name)); 73 | 74 | // Create new group form. 75 | $cancreateempty = $main->can_create_empty_group(); 76 | $cancreateandjoin = $main->can_create_and_join_group(); 77 | if ($cancreateempty || $cancreateandjoin) { 78 | $sesskey = sesskey(); 79 | $buttons = ''; 80 | if ($cancreateempty) { 81 | $buttons .= ""; 82 | } 83 | if ($cancreateandjoin) { 84 | $buttons .= ""; 85 | } 86 | $url = $PAGE->url; 87 | echo << 89 | 90 | Create new group: 91 | 92 | $buttons 93 | 94 | EOT; 95 | 96 | } 97 | 98 | $groups = $main->get_groups(); 99 | if ($groups) { 100 | foreach ($groups as $group) { 101 | echo "

".$group->get_formatted_name()."

"; 102 | foreach ($group->get_members() as $user) { 103 | echo '

'.fullname($user); 104 | if ($user->id == $USER->id && $main->can_leave_group($group)) { 105 | $leaveurl = new moodle_url($PAGE->url, ['sesskey' => sesskey(), 'leavegroup' => $group->get_id()]); 106 | echo ' '.html_writer::link($leaveurl, 'Leave'); 107 | } 108 | echo '

'; 109 | } 110 | if ($main->can_join_group($group)) { 111 | $joinurl = new moodle_url($PAGE->url, ['sesskey' => sesskey(), 'joingroup' => $group->get_id()]); 112 | echo '

'.html_writer::link($joinurl, 'Join group').'

'; 113 | } 114 | } 115 | } 116 | 117 | // Finish the page. 118 | echo $OUTPUT->footer(); 119 | -------------------------------------------------------------------------------- /mod_form.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * The main groupalloc configuration form 19 | * 20 | * It uses the standard core Moodle formslib. For more info about them, please 21 | * visit: http://docs.moodle.org/en/Development:lib/formslib.php 22 | * 23 | * @package mod_groupalloc 24 | * @copyright 2017 Marina Glancy 25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 | */ 27 | 28 | defined('MOODLE_INTERNAL') || die(); 29 | 30 | require_once($CFG->dirroot.'/course/moodleform_mod.php'); 31 | 32 | /** 33 | * Module instance settings form 34 | * 35 | * @package mod_groupalloc 36 | * @copyright 2017 Marina Glancy 37 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 | */ 39 | class mod_groupalloc_mod_form extends moodleform_mod { 40 | 41 | /** 42 | * Defines forms elements 43 | */ 44 | public function definition() { 45 | global $CFG, $COURSE; 46 | 47 | $mform = $this->_form; 48 | 49 | // Adding the "general" fieldset, where all the common settings are showed. 50 | $mform->addElement('header', 'general', get_string('general', 'form')); 51 | 52 | // Adding the standard "name" field. 53 | $mform->addElement('text', 'name', get_string('groupallocname', 'groupalloc'), array('size' => '64')); 54 | if (!empty($CFG->formatstringstriptags)) { 55 | $mform->setType('name', PARAM_TEXT); 56 | } else { 57 | $mform->setType('name', PARAM_CLEANHTML); 58 | } 59 | $mform->addRule('name', null, 'required', null, 'client'); 60 | $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); 61 | 62 | // Adding the standard "intro" and "introformat" fields. 63 | if ($CFG->branch >= 29) { 64 | $this->standard_intro_elements(); 65 | } else { 66 | $this->add_intro_editor(); 67 | } 68 | 69 | // Select grouping. 70 | $groupings = groups_get_all_groupings($COURSE->id); 71 | $choices = array_map(function ($grouping) { 72 | return format_string($grouping->name); 73 | }, $groupings); 74 | $context = context_course::instance($COURSE->id); 75 | $canmanagegroups = has_capability('moodle/course:managegroups', $context); 76 | if (empty($this->_cm) && $canmanagegroups) { 77 | $choices = [-1 => 'Create new grouping'] + $choices; // TODO lang 78 | } 79 | $choices = [0 => 'No grouping'] + $choices; // TODO lang 80 | 81 | $mform->addElement('select', 'usegroupingid', get_string('grouping', 'group'), $choices); 82 | 83 | if (empty($this->_cm) && $canmanagegroups) { 84 | $mform->addElement('text', 'newgroupingname', 'New grouping name', $choices); // TODO lang 85 | $mform->disabledIf('newgroupingname', 'usegroupingid', 'ne', -1); 86 | $mform->setType('newgroupingname', PARAM_TEXT); 87 | } 88 | 89 | if ($canmanagegroups) { 90 | $groupingslink = html_writer::link(new moodle_url('/group/groupings.php', ['id' => $COURSE->id]), 'Manage groupings'); // TODO lang 91 | $mform->addElement('static', 'managegroupings', '', $groupingslink); 92 | } 93 | 94 | // Different options 95 | $choices = [0 => 'Unlimited'] + array_combine([1,2,3,4,5], [1,2,3,4,5]); // TODO other choices? 96 | $mform->addElement('select', 'config_maxgroups', 'Maximum groups per person', $choices); // TODO lang 97 | $mform->setDefault('config_maxgroups', 1); 98 | 99 | $mform->addElement('text', 'config_minmembers', 'Minimum members in group'); // TODO lang 100 | $mform->setDefault('config_minmembers', 0); 101 | $mform->addRule('config_minmembers', null, 'numeric', null, 'client'); 102 | $mform->setType('config_minmembers', PARAM_INT); 103 | // TODO: add help that members will not be allowed to leave if the number of members is less than minimum. 104 | 105 | $mform->addElement('advcheckbox', 'config_autoremove', '', 'Automatically remove empty groups'); // TODO lang 106 | // TODO: add help that only groups created from this module will be removed. 107 | $mform->setDefault('config_autoremove', 1); 108 | 109 | $mform->addElement('text', 'config_maxmembers', 'Maximum members in group'); // TODO lang 110 | // TODO: add help that 0 or empty value means no limit. 111 | $mform->addRule('config_maxmembers', null, 'numeric', null, 'client'); 112 | $mform->setType('config_maxmembers', PARAM_INT); 113 | 114 | // Add standard grading elements. 115 | $this->standard_grading_coursemodule_elements(); 116 | 117 | // Add standard elements, common to all modules. 118 | $this->standard_coursemodule_elements(); 119 | 120 | // Add standard buttons, common to all modules. 121 | $this->add_action_buttons(); 122 | } 123 | 124 | /** 125 | * Only available on moodleform_mod. 126 | * 127 | * @param array $default_values passed by reference 128 | */ 129 | function data_preprocessing(&$default_values){ 130 | parent::data_preprocessing($default_values); 131 | if (!empty($default_values['config'])) { 132 | $values = json_decode($default_values['config'], true); 133 | foreach ($values as $key => $value) { 134 | $default_values['config_' . $key] = $value; 135 | } 136 | unset($default_values['config']); 137 | } 138 | } 139 | 140 | public function get_data() { 141 | $data = parent::get_data(); 142 | if ($data !== null) { 143 | $config = []; 144 | foreach ($data as $key => $value) { 145 | if (preg_match('/^config_(.*)$/', $key, $matches)) { 146 | $config[$matches[1]] = $value; 147 | unset($data->$key); 148 | } 149 | } 150 | $data->config = json_encode($config); 151 | } 152 | return $data; 153 | } 154 | 155 | // form verification 156 | function validation($data, $files) { 157 | global $COURSE, $DB, $CFG; 158 | $errors = parent::validation($data, $files); 159 | $mform = $this->_form; 160 | 161 | if ($data['config_minmembers'] > $data['config_maxmembers']) { 162 | $errors['config_maxmembers'] = 'Can not be less than minmembers'; // TODO lang 163 | } 164 | 165 | // TODO validate newgroupingname is specified and valid when usegroupingid == -1 166 | 167 | return $errors; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /classes/main.php: -------------------------------------------------------------------------------- 1 | cm = $cm; 19 | $this->activityrecord = $activityrecord; 20 | } 21 | 22 | public function get_cm() { 23 | return $this->cm; 24 | } 25 | 26 | public function get_activity_record() { 27 | return $this->activityrecord; 28 | } 29 | 30 | public function get_config($key) { 31 | if ($this->config === null) { 32 | $this->config = json_decode($this->activityrecord->config, true); 33 | } 34 | if (array_key_exists($key, $this->config)) { 35 | return $this->config[$key]; 36 | } 37 | return null; 38 | } 39 | 40 | public function get_groupingid() { 41 | return $this->activityrecord->usegroupingid; 42 | } 43 | 44 | public function can_create_empty_group() { 45 | if ($this->get_config(self::CONFIG_AUTOREMOVE)) { 46 | return false; 47 | } 48 | return has_capability('moodle/course:managegroups', $this->cm->context); 49 | } 50 | 51 | public function can_create_and_join_group() { 52 | return has_any_capability(['mod/groupalloc:creategroup', 'mod/groupalloc:createpasswordgroup', 53 | 'moodle/course:managegroups'], $this->cm->context) && 54 | $this->can_join_group(); 55 | } 56 | 57 | public function can_leave_group($group) { 58 | if (!has_capability('mod/groupalloc:leavegroup', $this->cm->context)) { 59 | return false; 60 | } 61 | $group = $this->get_group($group, IGNORE_MISSING); 62 | if ($group && !$group->is_member()) { 63 | // Not a member. 64 | return false; 65 | } 66 | $minmembers = $this->get_config(self::CONFIG_MINMEMBERS); 67 | if ($minmembers) { 68 | $members = $group->get_members(); 69 | if (count($members) <= $minmembers) { 70 | // Can not leave incomplete group. 71 | return false; 72 | } 73 | } 74 | return true; 75 | } 76 | 77 | public function can_join_group($group = null) { 78 | if (!has_capability('mod/groupalloc:joingroup', $this->cm->context)) { 79 | return false; 80 | } 81 | // TODO check user is enrolled. 82 | if ($group = $this->get_group($group)) { 83 | $maxmembers = $this->get_config(self::CONFIG_MAXMEMBERS); 84 | if ($group->is_member()) { 85 | // Already a member. 86 | return false; 87 | } 88 | if ($maxmembers && ($members = $group->get_members()) && count($members) >= $maxmembers) { 89 | // Group is full. 90 | return false; 91 | } 92 | } 93 | $maxgroups = $this->get_config(self::CONFIG_MAXGROUPS); 94 | if (!$maxgroups) { 95 | return true; 96 | } 97 | $usergroups = $this->get_user_groups(); 98 | return count($usergroups) < $maxgroups; 99 | } 100 | 101 | public function get_user_groups($user = null) { 102 | $usergroups = []; 103 | $groups = $this->get_groups(); 104 | foreach ($groups as $id => $group) { 105 | if ($group->is_member($user)) { 106 | $usergroups[$id] = $group; 107 | } 108 | } 109 | return $usergroups; 110 | } 111 | 112 | protected function create_group($name) { 113 | global $CFG; 114 | require_once($CFG->dirroot.'/group/lib.php'); 115 | $data = (object)[ 116 | 'name' => $name, 117 | 'courseid' => $this->cm->course 118 | ]; 119 | $groupid = groups_create_group($data); 120 | if ($groupingid = $this->get_groupingid()) { 121 | groups_assign_grouping($groupingid, $groupid); 122 | } 123 | return new mod_groupalloc_group($this, $groupid); 124 | } 125 | 126 | public function get_groups() { 127 | global $CFG; 128 | require_once($CFG->dirroot.'/group/lib.php'); 129 | if ($this->groups !== null) { 130 | return $this->groups; 131 | } 132 | $groupingid = $this->get_groupingid(); 133 | $groupsraw = groups_get_all_groups($this->cm->course, null, $groupingid); 134 | $this->groups = []; 135 | foreach ($groupsraw as $id => $data) { 136 | $this->groups[$id] = new mod_groupalloc_group($this, $data); 137 | } 138 | return $this->groups; 139 | } 140 | 141 | /** 142 | * @param mod_groupalloc_group $group 143 | * @param stdClass $user 144 | */ 145 | protected function join_group($group, $user = null) { 146 | global $CFG, $USER; 147 | require_once($CFG->dirroot.'/group/lib.php'); 148 | if ($user === null) { 149 | $user = $USER; 150 | } 151 | $group->add_member($user); 152 | } 153 | 154 | protected function leave_group($group, $user = null) { 155 | global $CFG, $USER; 156 | require_once($CFG->dirroot.'/group/lib.php'); 157 | if ($user === null) { 158 | $user = $USER; 159 | } 160 | $group->remove_member($user); 161 | $this->check_remove_empty_group($group); 162 | } 163 | 164 | protected function check_remove_empty_group($group) { 165 | global $CFG; 166 | require_once($CFG->dirroot.'/group/lib.php'); 167 | // TODO check this group was created inside this module 168 | if (!$this->get_config(self::CONFIG_AUTOREMOVE)) { 169 | return; 170 | } 171 | $members = $group->get_members(); 172 | if (empty($members)) { 173 | groups_delete_group($group->get_id()); 174 | } 175 | unset($this->groups[$group->get_id()]); 176 | } 177 | 178 | /** 179 | * @param int|stdClass|mod_groupalloc_group $groupid 180 | * @return mod_groupalloc_group|null 181 | */ 182 | protected function get_group($grouporid, $strictness = MUST_EXIST) { 183 | if ($grouporid === null) { 184 | return null; 185 | } 186 | $groups = $this->get_groups(); 187 | if ($grouporid instanceof mod_groupalloc_group) { 188 | $grouporid = $grouporid->get_id(); 189 | } else if (is_object($grouporid)) { 190 | $grouporid = $grouporid->id; 191 | } 192 | if (array_key_exists($grouporid, $groups)) { 193 | return $groups[$grouporid]; 194 | } 195 | if ($strictness == MUST_EXIST) { 196 | throw new moodle_exception('Group not found!'); 197 | } 198 | return null; 199 | } 200 | 201 | public function process_nonjs_actions() { 202 | $createempty = optional_param('createempty', null, PARAM_TEXT); 203 | $createjoin = optional_param('createjoin', null, PARAM_TEXT); 204 | $newgroupname = optional_param('newgroupname', null, PARAM_TEXT); // TODO Validate length and check security 205 | $newgroupname = trim($newgroupname); 206 | 207 | if ($createempty && $newgroupname && confirm_sesskey() && $this->can_create_empty_group()) { 208 | $group = $this->create_group($newgroupname); 209 | redirect($this->cm->url, 'Group '.$group->get_formatted_name().' created'); 210 | } 211 | 212 | if ($createjoin && $newgroupname && confirm_sesskey() && $this->can_create_and_join_group()) { 213 | $group = $this->create_group($newgroupname); 214 | $this->join_group($group); 215 | redirect($this->cm->url, 'You have created and joined the group '.$group->get_formatted_name()); 216 | } 217 | 218 | $joingroup = optional_param('joingroup', null, PARAM_INT); 219 | $leavegroup = optional_param('leavegroup', null, PARAM_INT); 220 | 221 | if ($joingroup && confirm_sesskey() && ($group = $this->get_group($joingroup)) && $this->can_join_group($group)) { 222 | $this->join_group($group); 223 | redirect($this->cm->url, 'You have joined the group '.$group->get_formatted_name()); 224 | } 225 | 226 | if ($leavegroup && confirm_sesskey() && ($group = $this->get_group($leavegroup)) && $this->can_leave_group($group)) { 227 | $this->leave_group($group); 228 | redirect($this->cm->url, 'You have left the group '.$group->get_formatted_name()); 229 | } 230 | 231 | } 232 | } -------------------------------------------------------------------------------- /lib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Library of interface functions and constants for module groupalloc 19 | * 20 | * All the core Moodle functions, neeeded to allow the module to work 21 | * integrated in Moodle should be placed here. 22 | * 23 | * All the groupalloc specific functions, needed to implement all the module 24 | * logic, should go to locallib.php. This will help to save some memory when 25 | * Moodle is performing actions across all modules. 26 | * 27 | * @package mod_groupalloc 28 | * @copyright 2017 Marina Glancy 29 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 | */ 31 | 32 | defined('MOODLE_INTERNAL') || die(); 33 | 34 | /** 35 | * Allow to protect groups with passwords. 36 | */ 37 | define('GROUPALLOC_FEATURE_PASSWORD', 1); 38 | 39 | /* Moodle core API */ 40 | 41 | /** 42 | * Returns the information on whether the module supports a feature 43 | * 44 | * See {@link plugin_supports()} for more info. 45 | * 46 | * @param string $feature FEATURE_xx constant for requested feature 47 | * @return mixed true if the feature is supported, null if unknown 48 | */ 49 | function groupalloc_supports($feature) { 50 | 51 | switch($feature) { 52 | case FEATURE_MOD_INTRO: 53 | return true; 54 | case FEATURE_SHOW_DESCRIPTION: 55 | return true; 56 | case FEATURE_GRADE_HAS_GRADE: 57 | return false; 58 | case FEATURE_BACKUP_MOODLE2: 59 | return true; 60 | case FEATURE_GROUPS: 61 | return false; 62 | case FEATURE_GROUPINGS: 63 | return false; 64 | case FEATURE_MODEDIT_DEFAULT_COMPLETION: 65 | return false; 66 | case FEATURE_COMPLETION_TRACKS_VIEWS: 67 | return false; 68 | case FEATURE_COMPLETION_HAS_RULES: 69 | return false; 70 | default: 71 | return null; 72 | } 73 | } 74 | 75 | /** 76 | * Saves a new instance of the groupalloc into the database 77 | * 78 | * Given an object containing all the necessary data, 79 | * (defined by the form in mod_form.php) this function 80 | * will create a new instance and return the id number 81 | * of the new instance. 82 | * 83 | * @param stdClass $groupalloc Submitted data from the form in mod_form.php 84 | * @param mod_groupalloc_mod_form $mform The form instance itself (if needed) 85 | * @return int The id of the newly inserted groupalloc record 86 | */ 87 | function groupalloc_add_instance(stdClass $groupalloc, mod_groupalloc_mod_form $mform = null) { 88 | global $DB, $CFG; 89 | 90 | $groupalloc->timecreated = time(); 91 | 92 | if ($groupalloc->usegroupingid == -1) { 93 | require_once($CFG->dirroot.'/group/lib.php'); 94 | $grouping = (object)['name' => $groupalloc->newgroupingname, 'courseid' => $groupalloc->course]; 95 | $groupalloc->usegroupingid = groups_create_grouping($grouping); 96 | } 97 | 98 | $groupalloc->id = $DB->insert_record('groupalloc', $groupalloc); 99 | 100 | //groupalloc_grade_item_update($groupalloc); 101 | 102 | return $groupalloc->id; 103 | } 104 | 105 | /** 106 | * Updates an instance of the groupalloc in the database 107 | * 108 | * Given an object containing all the necessary data, 109 | * (defined by the form in mod_form.php) this function 110 | * will update an existing instance with new data. 111 | * 112 | * @param stdClass $groupalloc An object from the form in mod_form.php 113 | * @param mod_groupalloc_mod_form $mform The form instance itself (if needed) 114 | * @return boolean Success/Fail 115 | */ 116 | function groupalloc_update_instance(stdClass $groupalloc, mod_groupalloc_mod_form $mform = null) { 117 | global $DB; 118 | 119 | $groupalloc->timemodified = time(); 120 | $groupalloc->id = $groupalloc->instance; 121 | 122 | // You may have to add extra stuff in here. 123 | 124 | $result = $DB->update_record('groupalloc', $groupalloc); 125 | 126 | //groupalloc_grade_item_update($groupalloc); 127 | 128 | return $result; 129 | } 130 | 131 | /** 132 | * This standard function will check all instances of this module 133 | * and make sure there are up-to-date events created for each of them. 134 | * If courseid = 0, then every groupalloc event in the site is checked, else 135 | * only groupalloc events belonging to the course specified are checked. 136 | * This is only required if the module is generating calendar events. 137 | * 138 | * @param int $courseid Course ID 139 | * @return bool 140 | */ 141 | function groupalloc_refresh_events($courseid = 0) { 142 | global $DB; 143 | 144 | if ($courseid == 0) { 145 | if (!$groupallocs = $DB->get_records('groupalloc')) { 146 | return true; 147 | } 148 | } else { 149 | if (!$groupallocs = $DB->get_records('groupalloc', array('course' => $courseid))) { 150 | return true; 151 | } 152 | } 153 | 154 | foreach ($groupallocs as $groupalloc) { 155 | // Create a function such as the one below to deal with updating calendar events. 156 | // groupalloc_update_events($groupalloc); 157 | } 158 | 159 | return true; 160 | } 161 | 162 | /** 163 | * Removes an instance of the groupalloc from the database 164 | * 165 | * Given an ID of an instance of this module, 166 | * this function will permanently delete the instance 167 | * and any data that depends on it. 168 | * 169 | * @param int $id Id of the module instance 170 | * @return boolean Success/Failure 171 | */ 172 | function groupalloc_delete_instance($id) { 173 | global $DB; 174 | 175 | if (! $groupalloc = $DB->get_record('groupalloc', array('id' => $id))) { 176 | return false; 177 | } 178 | 179 | // Delete any dependent records here. 180 | 181 | $DB->delete_records('groupalloc_group', array('groupallocid' => $groupalloc->id)); 182 | $DB->delete_records('groupalloc', array('id' => $groupalloc->id)); 183 | 184 | //groupalloc_grade_item_delete($groupalloc); 185 | 186 | return true; 187 | } 188 | 189 | /** 190 | * Returns a small object with summary information about what a 191 | * user has done with a given particular instance of this module 192 | * Used for user activity reports. 193 | * 194 | * $return->time = the time they did it 195 | * $return->info = a short text description 196 | * 197 | * @param stdClass $course The course record 198 | * @param stdClass $user The user record 199 | * @param cm_info|stdClass $mod The course module info object or record 200 | * @param stdClass $groupalloc The groupalloc instance record 201 | * @return stdClass|null 202 | */ 203 | function groupalloc_user_outline($course, $user, $mod, $groupalloc) { 204 | 205 | $return = new stdClass(); 206 | $return->time = 0; 207 | $return->info = ''; 208 | return $return; 209 | } 210 | 211 | /** 212 | * Prints a detailed representation of what a user has done with 213 | * a given particular instance of this module, for user activity reports. 214 | * 215 | * It is supposed to echo directly without returning a value. 216 | * 217 | * @param stdClass $course the current course record 218 | * @param stdClass $user the record of the user we are generating report for 219 | * @param cm_info $mod course module info 220 | * @param stdClass $groupalloc the module instance record 221 | */ 222 | function groupalloc_user_complete($course, $user, $mod, $groupalloc) { 223 | } 224 | 225 | /** 226 | * Given a course and a time, this module should find recent activity 227 | * that has occurred in groupalloc activities and print it out. 228 | * 229 | * @param stdClass $course The course record 230 | * @param bool $viewfullnames Should we display full names 231 | * @param int $timestart Print activity since this timestamp 232 | * @return boolean True if anything was printed, otherwise false 233 | */ 234 | function groupalloc_print_recent_activity($course, $viewfullnames, $timestart) { 235 | return false; 236 | } 237 | 238 | /** 239 | * Prepares the recent activity data 240 | * 241 | * This callback function is supposed to populate the passed array with 242 | * custom activity records. These records are then rendered into HTML via 243 | * {@link groupalloc_print_recent_mod_activity()}. 244 | * 245 | * Returns void, it adds items into $activities and increases $index. 246 | * 247 | * @param array $activities sequentially indexed array of objects with added 'cmid' property 248 | * @param int $index the index in the $activities to use for the next record 249 | * @param int $timestart append activity since this time 250 | * @param int $courseid the id of the course we produce the report for 251 | * @param int $cmid course module id 252 | * @param int $userid check for a particular user's activity only, defaults to 0 (all users) 253 | * @param int $groupid check for a particular group's activity only, defaults to 0 (all groups) 254 | */ 255 | function groupalloc_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0) { 256 | } 257 | 258 | /** 259 | * Prints single activity item prepared by {@link groupalloc_get_recent_mod_activity()} 260 | * 261 | * @param stdClass $activity activity record with added 'cmid' property 262 | * @param int $courseid the id of the course we produce the report for 263 | * @param bool $detail print detailed report 264 | * @param array $modnames as returned by {@link get_module_types_names()} 265 | * @param bool $viewfullnames display users' full names 266 | */ 267 | function groupalloc_print_recent_mod_activity($activity, $courseid, $detail, $modnames, $viewfullnames) { 268 | } 269 | 270 | /** 271 | * Returns all other caps used in the module 272 | * 273 | * For example, this could be array('moodle/site:accessallgroups') if the 274 | * module uses that capability. 275 | * 276 | * @return array 277 | */ 278 | function groupalloc_get_extra_capabilities() { 279 | return array(); 280 | } 281 | 282 | /* Gradebook API */ 283 | 284 | /** 285 | * Is a given scale used by the instance of groupalloc? 286 | * 287 | * This function returns if a scale is being used by one groupalloc 288 | * if it has support for grading and scales. 289 | * 290 | * @param int $groupallocid ID of an instance of this module 291 | * @param int $scaleid ID of the scale 292 | * @return bool true if the scale is used by the given groupalloc instance 293 | */ 294 | function groupalloc_scale_used($groupallocid, $scaleid) { 295 | global $DB; 296 | 297 | //if ($scaleid and $DB->record_exists('groupalloc', array('id' => $groupallocid, 'grade' => -$scaleid))) { 298 | // return true; 299 | //} else { 300 | return false; 301 | //} 302 | } 303 | 304 | /** 305 | * Checks if scale is being used by any instance of groupalloc. 306 | * 307 | * This is used to find out if scale used anywhere. 308 | * 309 | * @param int $scaleid ID of the scale 310 | * @return boolean true if the scale is used by any groupalloc instance 311 | */ 312 | function groupalloc_scale_used_anywhere($scaleid) { 313 | global $DB; 314 | 315 | //if ($scaleid and $DB->record_exists('groupalloc', array('grade' => -$scaleid))) { 316 | // return true; 317 | //} else { 318 | return false; 319 | //} 320 | } 321 | 322 | /** 323 | * Creates or updates grade item for the given groupalloc instance 324 | * 325 | * Needed by {@link grade_update_mod_grades()}. 326 | * 327 | * @param stdClass $groupalloc instance object with extra cmidnumber and modname property 328 | * @param bool $reset reset grades in the gradebook 329 | * @return void 330 | */ 331 | /*function groupalloc_grade_item_update(stdClass $groupalloc, $reset=false) { 332 | global $CFG; 333 | require_once($CFG->libdir.'/gradelib.php'); 334 | 335 | $item = array(); 336 | $item['itemname'] = clean_param($groupalloc->name, PARAM_NOTAGS); 337 | $item['gradetype'] = GRADE_TYPE_VALUE; 338 | 339 | if ($groupalloc->grade > 0) { 340 | $item['gradetype'] = GRADE_TYPE_VALUE; 341 | $item['grademax'] = $groupalloc->grade; 342 | $item['grademin'] = 0; 343 | } else if ($groupalloc->grade < 0) { 344 | $item['gradetype'] = GRADE_TYPE_SCALE; 345 | $item['scaleid'] = -$groupalloc->grade; 346 | } else { 347 | $item['gradetype'] = GRADE_TYPE_NONE; 348 | } 349 | 350 | if ($reset) { 351 | $item['reset'] = true; 352 | } 353 | 354 | grade_update('mod/groupalloc', $groupalloc->course, 'mod', 'groupalloc', 355 | $groupalloc->id, 0, null, $item); 356 | }*/ 357 | 358 | /** 359 | * Delete grade item for given groupalloc instance 360 | * 361 | * @param stdClass $groupalloc instance object 362 | * @return grade_item 363 | */ 364 | /*function groupalloc_grade_item_delete($groupalloc) { 365 | global $CFG; 366 | require_once($CFG->libdir.'/gradelib.php'); 367 | 368 | return grade_update('mod/groupalloc', $groupalloc->course, 'mod', 'groupalloc', 369 | $groupalloc->id, 0, null, array('deleted' => 1)); 370 | }*/ 371 | 372 | /** 373 | * Update groupalloc grades in the gradebook 374 | * 375 | * Needed by {@link grade_update_mod_grades()}. 376 | * 377 | * @param stdClass $groupalloc instance object with extra cmidnumber and modname property 378 | * @param int $userid update grade of specific user only, 0 means all participants 379 | */ 380 | /*function groupalloc_update_grades(stdClass $groupalloc, $userid = 0) { 381 | global $CFG, $DB; 382 | require_once($CFG->libdir.'/gradelib.php'); 383 | 384 | // Populate array of grade objects indexed by userid. 385 | $grades = array(); 386 | 387 | grade_update('mod/groupalloc', $groupalloc->course, 'mod', 'groupalloc', $groupalloc->id, 0, $grades); 388 | }*/ 389 | 390 | /* File API */ 391 | 392 | /** 393 | * Returns the lists of all browsable file areas within the given module context 394 | * 395 | * The file area 'intro' for the activity introduction field is added automatically 396 | * by {@link file_browser::get_file_info_context_module()} 397 | * 398 | * @param stdClass $course 399 | * @param stdClass $cm 400 | * @param stdClass $context 401 | * @return array of [(string)filearea] => (string)description 402 | */ 403 | function groupalloc_get_file_areas($course, $cm, $context) { 404 | return array(); 405 | } 406 | 407 | /** 408 | * File browsing support for groupalloc file areas 409 | * 410 | * @package mod_groupalloc 411 | * @category files 412 | * 413 | * @param file_browser $browser 414 | * @param array $areas 415 | * @param stdClass $course 416 | * @param stdClass $cm 417 | * @param stdClass $context 418 | * @param string $filearea 419 | * @param int $itemid 420 | * @param string $filepath 421 | * @param string $filename 422 | * @return file_info instance or null if not found 423 | */ 424 | function groupalloc_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { 425 | return null; 426 | } 427 | 428 | /** 429 | * Serves the files from the groupalloc file areas 430 | * 431 | * @package mod_groupalloc 432 | * @category files 433 | * 434 | * @param stdClass $course the course object 435 | * @param stdClass $cm the course module object 436 | * @param stdClass $context the groupalloc's context 437 | * @param string $filearea the name of the file area 438 | * @param array $args extra arguments (itemid, path) 439 | * @param bool $forcedownload whether or not force download 440 | * @param array $options additional options affecting the file serving 441 | */ 442 | function groupalloc_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options=array()) { 443 | global $DB, $CFG; 444 | 445 | if ($context->contextlevel != CONTEXT_MODULE) { 446 | send_file_not_found(); 447 | } 448 | 449 | require_login($course, true, $cm); 450 | 451 | send_file_not_found(); 452 | } 453 | 454 | /* Navigation API */ 455 | 456 | /** 457 | * Extends the global navigation tree by adding groupalloc nodes if there is a relevant content 458 | * 459 | * This can be called by an AJAX request so do not rely on $PAGE as it might not be set up properly. 460 | * 461 | * @param navigation_node $navref An object representing the navigation tree node of the groupalloc module instance 462 | * @param stdClass $course current course record 463 | * @param stdClass $module current groupalloc instance record 464 | * @param cm_info $cm course module information 465 | */ 466 | //function groupalloc_extend_navigation(navigation_node $navref, stdClass $course, stdClass $module, cm_info $cm) { 467 | // TODO Delete this function and its docblock, or implement it. 468 | //} 469 | 470 | /** 471 | * Extends the settings navigation with the groupalloc settings 472 | * 473 | * This function is called when the context for the page is a groupalloc module. This is not called by AJAX 474 | * so it is safe to rely on the $PAGE. 475 | * 476 | * @param settings_navigation $settingsnav complete settings navigation tree 477 | * @param navigation_node $groupallocnode groupalloc administration node 478 | */ 479 | //function groupalloc_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $groupallocnode=null) { 480 | // TODO Delete this function and its docblock, or implement it. 481 | //} 482 | --------------------------------------------------------------------------------