Commit d600136b authored by Richard Mansfield's avatar Richard Mansfield Committed by Gerrit Code Review
Browse files

Merge changes I4010413f,I3f51f0ed,I6df7f9df,Ie13b7255,I8bb0940a,Ie2e5b81c,Ib58aa496,I7e72a773

* changes:
  Add function to get groups with the properties expected by update_group()
  Allow per-group page editing permissions
  Enable submissions per-group, and decouple from 'course' groups
  Add subheadings to create/edit group settings
  Add more flexible group jointypes (bug #610690)
  Combine group create & edit pages
  Remove can_become_admin check when changing group roles
  Remove hardcoded references to 'tutor' role in core code (bug #827762)
parents d8a43c2e bc9e1b89
......@@ -44,8 +44,13 @@ $ALLOWEDKEYS = array(
'shortname',
'displayname',
'description',
'grouptype',
'open',
'controlled',
'request',
'roles',
'public',
'submitpages',
'editroles',
);
if ($USER->get('admin')) {
$ALLOWEDKEYS[] = 'usersautoadded';
......@@ -54,15 +59,11 @@ if ($USER->get('admin')) {
$MANDATORYFIELDS = array(
'shortname',
'displayname',
'grouptype',
'roles',
);
$UPDATES = array(); // During validation, remember which group already exist
$JOINTYPES = array();
foreach (group_get_grouptypes() as $type) {
safe_require('grouptype', $type);
$JOINTYPES[$type] = call_static_method('GroupType' . $type, 'allowed_join_types');
}
$GROUPTYPES = group_get_grouptype_options();
$EDITROLES = group_get_editroles_options();
$form = array(
'name' => 'uploadcsv',
......@@ -99,7 +100,7 @@ $form = array(
* @param array $values The values submitted
*/
function uploadcsv_validate(Pieform $form, $values) {
global $CSVDATA, $ALLOWEDKEYS, $MANDATORYFIELDS, $JOINTYPES, $FORMAT, $USER, $UPDATES;
global $CSVDATA, $ALLOWEDKEYS, $MANDATORYFIELDS, $GROUPTYPES, $FORMAT, $USER, $UPDATES, $EDITROLES;
// Don't even start attempting to parse if there are previous errors
if ($form->has_errors()) {
......@@ -153,7 +154,14 @@ function uploadcsv_validate(Pieform $form, $values) {
$shortname = $line[$formatkeylookup['shortname']];
$displayname = $line[$formatkeylookup['displayname']];
$grouptype = $line[$formatkeylookup['grouptype']];
$grouptype = $line[$formatkeylookup['roles']];
$open = isset($formatkeylookup['open']) && !empty($line[$formatkeylookup['open']]);
$controlled = isset($formatkeylookup['controlled']) && !empty($line[$formatkeylookup['controlled']]);
$request = isset($formatkeylookup['request']) && !empty($line[$formatkeylookup['request']]);
$submitpages = isset($formatkeylookup['submitpages']) && !empty($line[$formatkeylookup['submitpages']]);
if (isset($formatkeylookup['editroles'])) {
$editroles = $line[$formatkeylookup['editroles']];
}
if (!preg_match('/^[a-zA-Z0-9_.-]{2,255}$/', $shortname)) {
$csverrors->add($i, get_string('uploadgroupcsverrorinvalidshortname', 'admin', $i, $shortname));
......@@ -172,7 +180,7 @@ function uploadcsv_validate(Pieform $form, $values) {
$shortnames[$shortname] = array(
'shortname' => $shortname,
'displayname' => $displayname,
'grouptype' => $grouptype,
'roles' => $grouptype,
'lineno' => $i,
'raw' => $line,
);
......@@ -203,16 +211,20 @@ function uploadcsv_validate(Pieform $form, $values) {
}
$displaynames[strtolower($displayname)] = 1;
$groupjointype = split('/', $grouptype);
if (count($groupjointype) != 2) {
if (!isset($GROUPTYPES[$grouptype])) {
$csverrors->add($i, get_string('uploadgroupcsverrorinvalidgrouptype', 'admin', $i, $grouptype));
}
else {
if (!isset($JOINTYPES[$groupjointype[0]]) || !in_array($groupjointype[1], $JOINTYPES[$groupjointype[0]])) {
$csverrors->add($i, get_string('uploadgroupcsverrorinvalidgrouptype', 'admin', $i, $grouptype));
}
if (isset($editroles) && !isset($EDITROLES[$editroles])) {
$csverrors->add($i, get_string('uploadgroupcsverrorinvalideditroles', 'admin', $i, $editroles));
}
if ($open && $controlled) {
$csverrors->add($i, get_string('uploadgroupcsverroropencontrolled', 'admin', $i));
}
if ($open && $request) {
$csverrors->add($i, get_string('uploadgroupcsverroropenrequest', 'admin', $i));
}
if ($values['updategroups']) {
......@@ -259,16 +271,18 @@ function uploadcsv_submit(Pieform $form, $values) {
foreach ($CSVDATA as $record) {
$groupjointype = split('/', $record[$formatkeylookup['grouptype']]);
$group = new StdClass;
$group->name = $record[$formatkeylookup['displayname']];
$group->shortname = $record[$formatkeylookup['shortname']];
$group->institution = $institution;
$group->grouptype = $groupjointype[0];
$group->jointype = $groupjointype[1];
$group->grouptype = $record[$formatkeylookup['roles']];
foreach ($FORMAT as $field) {
if ($field == 'displayname' || $field == 'shortname' || $field == 'grouptype') {
if ($field == 'displayname' || $field == 'shortname' || $field == 'roles') {
continue;
}
if ($field == 'submitpages') {
$group->submittableto = $record[$formatkeylookup[$field]];
continue;
}
$group->{$field} = $record[$formatkeylookup[$field]];
......@@ -316,23 +330,29 @@ function uploadcsv_submit(Pieform $form, $values) {
}
$grouptypes = "<ul class=fieldslist>\n";
foreach ($JOINTYPES as $grouptype => $jointypes) {
foreach ($jointypes as $type) {
$grouptypes .= '<li>' . hsc($grouptype) . '/' . hsc($type) . "</li>\n";
}
foreach (array_keys($GROUPTYPES) as $grouptype) {
$grouptypes .= '<li>' . hsc($grouptype) . "</li>\n";
}
$grouptypes .= "<div class=cl></div></ul>\n";
$editroles = "<ul class=fieldslist>\n";
foreach (array_keys($EDITROLES) as $editrole) {
$editroles .= '<li>' . hsc($editrole) . "</li>\n";
}
$editroles .= "<div class=cl></div></ul>\n";
$grouptypes .= get_string('uploadgroupcsveditrolesdescription', 'admin', get_help_icon('core', 'groups', 'editgroup', 'editroles'), $editroles);
$fields = "<ul class=fieldslist>\n";
foreach ($ALLOWEDKEYS as $type) {
$helplink = '';
if ($type == 'grouptype' || $type == 'public' || $type == 'usersautoadded') {
$helplink = get_help_icon('core', 'groups', 'creategroup', $type);
if ($type == 'public' || $type == 'usersautoadded') {
$helplink = get_help_icon('core', 'groups', 'editgroup', $type);
}
$fields .= '<li>' . hsc($type) . $helplink . "</li>\n";
}
$fields .= "<div class=cl></div></ul>\n";
$uploadcsvpagedescription = get_string('uploadgroupcsvpagedescription2', 'admin', get_help_icon('core', 'groups', 'creategroup', 'grouptype'), $grouptypes, $fields);
$uploadcsvpagedescription = get_string('uploadgroupcsvpagedescription2', 'admin', get_help_icon('core', 'groups', 'editgroup', 'grouptype'), $grouptypes, $fields);
$form = pieform($form);
......
......@@ -171,7 +171,7 @@ $elements = array(
),
'general' => array(
'type' => 'fieldset',
'legend' => get_string('general', 'artefact.internal'),
'legend' => get_string('general'),
'class' => $fieldset != 'general' ? 'collapsed' : '',
'elements' => $items
),
......
......@@ -44,7 +44,6 @@ $string['viewmyprofile'] = 'View my profile';
$string['aboutme'] = 'About me';
$string['contact'] = 'Contact information';
$string['messaging'] = 'Messaging';
$string['general'] = 'General';
// profile fields
$string['firstname'] = 'First Name';
......
......@@ -958,12 +958,14 @@ class User {
}
$group = $v->get('group');
if ($group) {
$editroles = $v->get('editingroles');
$this->reset_grouproles();
if ($v->get('type') == 'grouphomepage' && $this->grouproles[$group] != 'admin') {
return false;
}
return isset($this->grouproles[$group]) && in_array($this->grouproles[$group], $editroles);
if (!isset($this->grouproles[$group])) {
return false;
}
return group_role_can_edit_views($group, $this->grouproles[$group]);
}
return false;
}
......
......@@ -162,7 +162,7 @@ class PluginBlocktypeGroupViews extends SystemBlocktype {
}
}
if (group_allows_submission($group->grouptype) && ($userviewdata = View::get_user_views())) {
if ($group->submittableto && ($userviewdata = View::get_user_views())) {
require_once('pieforms/pieform.php');
// A user can submit more than one view to the same group, but no view can be
// submitted to more than one group.
......
......@@ -39,36 +39,39 @@ $data['message'] = null;
$initialgroups = param_integer_list('initialgroups', array());
$resultgroups = param_integer_list('resultgroups', array());
$userid = param_integer('userid');
$jointype = param_variable('jointype');
$addtype = param_variable('addtype');
// Prevent group membership changing done by ordinary members, Tutors can only
// add members to group and cannot remove anyone. Group admins can do anything.
// With regard to invitation, both admins and tutors can invite people.
foreach (array_unique(array_merge($initialgroups, $resultgroups)) as $groupid) {
if (!group_user_access($groupid)) {
$allgroups = array_unique(array_merge($initialgroups, $resultgroups));
$groupdata = get_records_select_assoc(
'group',
'id IN (' . join(',', array_fill(0, count($allgroups), '?')) . ')',
$allgroups
);
foreach (group_get_grouptypes() as $grouptype) {
safe_require('grouptype', $grouptype);
}
foreach ($allgroups as $groupid) {
if (!$loggedinrole = group_user_access($groupid)) {
json_reply('local', get_string('accessdenied', 'error'));
break;
}
switch (group_user_access($groupid)) {
case 'member':
json_reply('local', get_string('accessdenied', 'error'));
break;
case 'tutor':
if ($usertype = group_user_access($groupid, $userid)) {
if (($usertype == 'member') && in_array($groupid, array_diff($initialgroups, $resultgroups))) {
json_reply('local', get_string('cantremovemember', 'group'));
}
elseif ($usertype != 'member' && in_array($groupid, array_diff($initialgroups, $resultgroups))) {
json_reply('local', get_string('cantremoveuserisadmin', 'group'));
}
}
if ($loggedinrole == 'admin') {
continue;
}
if (!in_array($loggedinrole, call_static_method('GroupType' . $groupdata[$groupid]->grouptype, 'get_view_assessing_roles'))) {
json_reply('local', get_string('accessdenied', 'error'));
}
if (group_user_access($groupid, $userid) && in_array($groupid, array_diff($initialgroups, $resultgroups))) {
json_reply('local', get_string('cantremovememberfromgroup', 'group', hsc($groupdata[$groupid]->name)));
}
}
$groupdata = get_records_select_assoc('group', 'id IN (' . join(',', array_unique(array_merge($initialgroups, $resultgroups))) . ')');
if ($jointype == 'controlled') {
if ($addtype == 'add') {
db_begin();
//remove group membership
if ($groupstoremove = array_diff($initialgroups, $resultgroups)) {
......@@ -108,7 +111,7 @@ if ($jointype == 'controlled') {
activity_occurred('maharamessage', $n);
$data['message'] = get_string('changedgroupmembership', 'group');
}
elseif ($jointype == 'invite') {
else if ($addtype == 'invite') {
if ($groupstoadd = array_diff($resultgroups, $initialgroups)) {
foreach ($groupstoadd as $groupid) {
group_invite_user($groupdata[$groupid], $userid, $USER->get('id'));
......
......@@ -34,7 +34,7 @@ require(dirname(dirname(__FILE__)) . '/init.php');
$userid = param_integer('userid');
$groupdata = array();
$initialgroups = array('controlled' => array(), 'invite' => array());
$initialgroups = array('add' => array(), 'invite' => array());
/* Get (a) controlled membership groups,
(b) request membership groups where the displayed user has requested membership,
......@@ -60,7 +60,7 @@ $controlled = get_records_sql_array("SELECT g.*, gm.role,
JOIN {grouptype_roles} gtr ON (gtr.grouptype = g.grouptype AND gtr.role = gm.role)
LEFT JOIN {group_member_request} gmr ON (gmr.member = ? AND gmr.group = g.id)
WHERE gm.member = ?
AND (g.jointype = 'controlled' OR (g.jointype = 'request' AND gmr.member = ?))
AND (g.jointype = 'controlled' OR (g.request = 1 AND gmr.member = ?))
AND (gm.role = 'admin' OR gtr.see_submitted_views = 1)
AND g.deleted = 0", array($userid, $userid, $userid, $USER->get('id'), $userid));
......@@ -68,16 +68,16 @@ if ($controlled) {
foreach ($controlled as &$g) {
if ($g->member) {
$g->checked = true;
$initialgroups['controlled'][] = $g->id;
$initialgroups['add'][] = $g->id;
if ($g->role != 'admin') {
$g->disabled = true;
}
}
}
$groupdata['controlled'] = $controlled;
$groupdata['add'] = $controlled;
}
/* Get 'Invite olny' groups where the logged in user is a group admin.
/* Get groups where the logged in user is a group admin.
@return array A data structure containing results looking like ...
* $results = array(
* array(
......@@ -95,7 +95,6 @@ $invite = get_records_sql_array("SELECT g.*, gm.role,
FROM {group} g
JOIN {group_member} gm ON (gm.group = g.id)
WHERE gm.member = ?
AND g.jointype = 'invite'
AND gm.role = 'admin'
AND g.deleted = 0", array($userid, $userid, $USER->get('id')));
......
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
* http://wiki.mahara.org/Contributors
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package mahara
* @subpackage core
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
*
*/
define('INTERNAL', 1);
define('MENUITEM', 'groups/groupsiown');
require(dirname(dirname(__FILE__)) . '/init.php');
require_once('pieforms/pieform.php');
require_once('group.php');
define('TITLE', get_string('creategroup', 'group'));
if (!group_can_create_groups()) {
throw new AccessDeniedException(get_string('accessdenied', 'error'));
}
$elements = array();
$elements['name'] = array(
'type' => 'text',
'title' => get_string('groupname', 'group'),
'rules' => array( 'required' => true, 'maxlength' => 128 ));
$elements['description'] = array(
'type' => 'wysiwyg',
'title' => get_string('groupdescription', 'group'),
'rules' => array('maxlength' => 65536),
'rows' => 10,
'cols' => 55);
$grouptypeoptions = group_get_grouptype_options();
if ($grouptypeparam = param_alphanumext('grouptype', 0) and isset($grouptypeoptions[$grouptypeparam])) {
$elements['grouptype'] = array(
'type' => 'hidden',
'value' => $grouptypeparam,
);
}
else {
$elements['grouptype'] = array(
'type' => 'select',
'title' => get_string('grouptype', 'group'),
'options' => $grouptypeoptions,
'defaultvalue' => 'standard.open',
'help' => true
);
}
if (get_config('allowgroupcategories')
&& ($groupcategories = get_records_menu('group_category','','','displayorder', 'id,title'))) {
if ($groupcategoryparam = param_integer('category', 0) and isset($groupcategories[$groupcategoryparam])) {
$elements['category'] = array(
'type' => 'hidden',
'value' => $groupcategoryparam,
);
}
else {
$elements['category'] = array(
'type' => 'select',
'title' => get_string('groupcategory', 'group'),
'options' => array('0'=>get_string('nocategoryselected', 'group')) + $groupcategories,
'defaultvalue' => ''
);
}
}
$publicallowed = get_config('createpublicgroups') == 'all' || (get_config('createpublicgroups') == 'admins' && $USER->get('admin'));
if (!param_variable('creategroup_submit', null)) {
// If 'public=0' param is passed on first page load, hide the public checkbox.
$publicparam = param_integer('public', null);
}
$elements['public'] = array(
'type' => 'checkbox',
'title' => get_string('publiclyviewablegroup', 'group'),
'description' => get_string('publiclyviewablegroupdescription', 'group'),
'help' => true,
'ignore' => !$publicallowed || (isset($publicparam) && $publicparam === 0),
);
$elements['usersautoadded'] = array(
'type' => 'checkbox',
'title' => get_string('usersautoadded', 'group'),
'description' => get_string('usersautoaddeddescription', 'group'),
'help' => true,
'ignore' => !$USER->get('admin'));
$elements['viewnotify'] = array(
'type' => 'checkbox',
'title' => get_string('viewnotify', 'group'),
'description' => get_string('viewnotifydescription', 'group'),
'defaultvalue' => 1
);
$elements['submit'] = array(
'type' => 'submitcancel',
'name' => 'creategroup_submit',
'value' => array(get_string('savegroup', 'group'), get_string('cancel'))
);
$creategroup = pieform(array(
'name' => 'creategroup',
'method' => 'post',
'plugintype' => 'core',
'pluginname' => 'groups',
'elements' => $elements
));
$smarty = smarty();
$smarty->assign('form', $creategroup);
$smarty->assign('PAGEHEADING', TITLE);
$smarty->display('form.tpl');
function creategroup_validate(Pieform $form, $values) {
// This check has not always been case-insensitive; don't use get_record in case we get >1 row back.
if (get_records_sql_array('SELECT id FROM {group} WHERE LOWER(TRIM(name)) = ?', array(strtolower(trim($values['name']))))) {
$form->set_error('name', get_string('groupalreadyexists', 'group'));
}
}
function creategroup_cancel_submit() {
redirect('/group/mygroups.php');
}
function creategroup_submit(Pieform $form, $values) {
global $USER;
global $SESSION;
list($grouptype, $jointype) = explode('.', $values['grouptype']);
$values['public'] = (isset($values['public'])) ? $values['public'] : 0;
$values['usersautoadded'] = (isset($values['usersautoadded'])) ? $values['usersautoadded'] : 0;
$id = group_create(array(
'name' => trim($values['name']),
'description' => $values['description'],
'grouptype' => $grouptype,
'category' => empty($values['category']) ? null : intval($values['category']),
'jointype' => $jointype,
'public' => intval($values['public']),
'usersautoadded' => intval($values['usersautoadded']),
'members' => array($USER->get('id') => 'admin'),
'viewnotify' => intval($values['viewnotify']),
));
$USER->reset_grouproles();
$SESSION->add_ok_msg(get_string('groupsaved', 'group'));
redirect('/group/view.php?id=' . $id);
}
......@@ -30,51 +30,207 @@ define('MENUITEM', 'groups/groupsiown');
require(dirname(dirname(__FILE__)) . '/init.php');
require_once('pieforms/pieform.php');
require_once('group.php');
define('TITLE', get_string('editgroup', 'group'));
$id = param_integer('id');
define('GROUP', $id);
if ($id = param_integer('id', null)) {
define('TITLE', get_string('editgroup', 'group'));
define('GROUP', $id);
$group_data = get_record_sql("SELECT g.*
FROM {group} g
INNER JOIN {group_member} gm ON (gm.group = g.id AND gm.member = ? AND gm.role = 'admin')
WHERE g.id = ?
AND g.deleted = 0", array($USER->get('id'), $id));
if (!group_user_access($id)) {
$SESSION->add_error_msg(get_string('canteditdontown', 'group'));
redirect('/group/mygroups.php');
}
if (!$group_data) {
$SESSION->add_error_msg(get_string('canteditdontown', 'group'));
redirect('/group/mygroups.php');
$group_data = group_get_groups_for_editing(array($id));
if (count($group_data) != 1) {
throw new GroupNotFoundException(get_string('groupnotfound', 'group', $id));
}
$group_data = $group_data[0];
}
$elements = array();
$elements['name'] = array(
else {
define('TITLE', get_string('creategroup', 'group'));
if (!group_can_create_groups()) {
throw new AccessDeniedException(get_string('accessdenied', 'error'));
}
$group_data = (object) array(
'id' => null,
'name' => null,
'description' => null,
'grouptype' => 'standard',
'open' => 1,
'controlled' => 0,
'category' => 0,
'public' => 0,
'usersautoadded' => 0,
'viewnotify' => 1,
'submittableto' => 0,
'editroles' => 'all',
);
}
$form = array(
'name' => 'editgroup',
'plugintype' => 'core',
'pluginname' => 'groups',
'elements' => array(
'name' => array(
'type' => 'text',
'title' => get_string('groupname', 'group'),
'rules' => array( 'required' => true, 'maxlength' => 128 ),
'defaultvalue' => $group_data->name);
$elements['description'] = array(
'defaultvalue' => $group_data->name,
),
'description' => array(
'type' => 'wysiwyg',
'title' => get_string('groupdescription', 'group'),
'rules' => array('maxlength' => 65536),
'rows' => 10,
'cols' => 55,
'defaultvalue' => $group_data->description);
'defaultvalue' => $group_data->description,
),
'settings' => array(
'type' => 'fieldset',
'collapsible' => true,
'collapsed' => false,
'class' => 'sectioned',
'legend' => get_string('settings'),
'elements' => array(),
),
'submit' => array(
'type' => 'submitcancel',
'value' => array(get_string('savegroup', 'group'), get_string('cancel'))
),
),
);
$grouptypeoptions = group_get_grouptype_options($group_data->grouptype);
$currenttype = $group_data->grouptype . '.' . $group_data->jointype;
if (!isset($grouptypeoptions[$currenttype])) {
// The user can't create groups of this type. Probably a non-staff user
// who's been promoted to admin of a controlled group. Just don't let
// them change it.
$grouptypeoptions = array($currenttype => get_string('membershiptype.' . $group_data->jointype, 'group'));
$elements = array();
$elements['membership'] = array(
'type' => 'html',
'title' => get_string('Membership', 'group'),
'value' => '',
);
$cancreatecontrolled = $USER->get('admin') || $USER->get('staff')
|| $USER->is_institutional_admin() || $USER->is_institutional_staff();
$elements['open'] = array(
'type' => 'checkbox',
'title' => get_string('Open', 'group'),
'description' => get_string('opendescript