Commit 33b484bf authored by Robert Lyon's avatar Robert Lyon
Browse files

Bug 1594579: Allowing a group to be duplicated



This patch does the copying of:

- The group settings - and renames the group to a new unique name
- Views/collections - the same way we copy them now so that copied files
  end up in 'viewfiles' folder.
- The group homepage by copying the old homepage like a normal
page then move the blocks from it to the new homepage and then deleting the
duplicated homepage.
- Adding copy buttons to the admin/groups list, the my groups list,
and group homepage.

Still to do:

Make sure we don't duplicate more than one copy of a journal if the
journal is within more than one page/block

behatnotneeded - behat file to come later

Change-Id: Ibd74d1bdf76c3488d4af3735dba9c7b5f773e2f7
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent 9d6b85cf
<?php
/**
*
* @package mahara
* @subpackage core
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
define('INTERNAL', 1);
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'group');
define('SECTION_PAGE', 'copy');
require(dirname(dirname(__FILE__)) . '/init.php');
require_once(get_config('libroot') . 'view.php');
require_once(get_config('libroot') . 'group.php');
$groupid = param_integer('id');
$return = param_alphanum('return', null);
// Check the group exists
if (!get_record('group', 'id', $groupid)) {
throw new GroupNotFoundException(get_string('groupnotfound', 'group', $groupid));
}
// Check for group role of the user doing the copying
$userid = $USER->get('id');
$role = group_user_access($groupid, $userid);
if (!($USER->get('admin') || $role == 'admin')) {
throw new AccessDeniedException();
}
group_copy($groupid, $return);
......@@ -15,6 +15,7 @@ defined('INTERNAL') || die();
$string['groupname'] = 'Group name';
$string['groupshortname'] = 'Short name';
$string['creategroup'] = 'Create group';
$string['copygroup'] = 'Copy group "%s"';
$string['groupmemberrequests'] = 'Pending membership requests';
$string['membershiprequests'] = 'Membership requests';
$string['sendinvitation'] = 'Send invite';
......
......@@ -2751,3 +2751,175 @@ function group_get_membership_file_data($group_id, $file_format = 'csv', $mimety
return $data;
}
/**
* Duplicate group - make a copy of the the group's pages, collections and group settings.
* @param string/int $groupid The id of the group to copy
* @param string $return The place to return to after the copying
*
* @TODO: Copy forums / files / journals not associated with views/blocks.
* @TODO: Copy existing members to new group.
*/
function group_copy($groupid, $return) {
global $USER, $SESSION;
$userid = $USER->get('id');
$role = group_user_access($groupid, $userid);
if (!($USER->get('admin') || $role == 'admin')) {
throw new AccessDeniedException();
}
// Copy the group
$group = get_record_select('group', 'id = ? AND deleted = 0', array($groupid), '*, ' . db_format_tsfield('ctime'));
unset($group->id);
$group->ctime = $group->mtime = db_format_timestamp(time());
// need to update the name
$group->name = new_group_name($group->name);
$group->shortname = group_generate_shortname($group->shortname);
if (empty($group->institution)) {
$group->institution = 'mahara';
}
if (isset($group->urlid)) {
// need to sort out the cleanurl
$group->urlid = generate_urlid($group->name, get_config('cleanurlviewdefault'), 3, 100);
}
db_begin();
$newvalues = (array)$group;
$newvalues[$newvalues['jointype']] = 1;
unset($newvalues['jointype']);
$newvalues['members'] = array($USER->get('id') => 'admin');
$new_groupid = group_create($newvalues);
$USER->reset_grouproles();
// Now update the description with any embedded image info
$newvalues['description'] = EmbeddedImage::prepare_embedded_images($newvalues['description'], 'group', $new_groupid, $groupid);
$newvalues['id'] = $new_groupid;
unset($newvalues['members']);
unset($newvalues['ctime']);
unset($newvalues['mtime']);
group_update((object)$newvalues);
/*
@TODO: Allow copying of the file artefacts
$artefactmap = array(); // store the old ids and have them map to new ids
$oldartefacts = get_records_assoc('artefact', 'group', $groupid, 'artefacttype, id');
foreach ($oldartefacts as $artefact) {
$a = artefact_instance_from_id($artefact->id);
$artefactmap[$artefact->id] = $a->copy_for_new_owner(null, $new_groupid, null);
$a->commit();
}
*/
// Copy views for the new group
$templates = get_records_sql_array("
SELECT v.id, v.title, v.description, v.type
FROM {view} v
LEFT JOIN {collection_view} cv ON v.id = cv.view
WHERE v.group = ?
AND cv.view IS NULL", array($groupid));
if ($templates) {
require_once(get_config('libroot') . 'view.php');
foreach ($templates as $template) {
list($view) = View::create_from_template(array(
'group' => $new_groupid,
'title' => $template->title,
'description' => $template->description,
), $template->id, null, false);
if ($template->type == 'grouphomepage') {
$duplicate_homepage = $view;
}
$view->set_access(array(array(
'type' => 'group',
'id' => $new_groupid,
'startdate' => null,
'stopdate' => null,
'role' => null
)));
}
// Now update new homepage with the duplicated old one - it's blocks should be connected
// to any new artefacts created.
$new_homepage = get_record('view', 'group', $new_groupid, 'type', 'grouphomepage');
delete_records('block_instance', 'view', $new_homepage->id);
$old_homepage_blocks = get_records_sql_array("
SELECT bi.* FROM {block_instance} bi
JOIN {view} v ON v.id = bi.view
WHERE v.id = ?", array($duplicate_homepage->get('id')));
foreach ($old_homepage_blocks as $block) {
unset($block->id);
$block->view = $new_homepage->id;
insert_record('block_instance', $block);
}
// Add back correct layout
update_record('view', array(
'layout' => $duplicate_homepage->get('layout'),
'numrows' => $duplicate_homepage->get('numrows'),
), array('id' => $new_homepage->id));
// Clear the existing view_rows_columns and add in correct ones
delete_records('view_rows_columns', 'view', $new_homepage->id);
$rowscolumns = $duplicate_homepage->get('columnsperrow');
foreach ($rowscolumns as $row) {
insert_record('view_rows_columns', array(
'row' => $row->row,
'columns' => $row->columns,
'view' => $new_homepage->id)
);
}
// Now delete the duplicate homepage
$duplicate_homepage->delete();
}
// Copy collections for the new group
$templates = get_records_sql_array("
SELECT DISTINCT c.id, c.name
FROM {view} v
INNER JOIN {collection_view} cv ON v.id = cv.view
INNER JOIN {collection} c ON cv.collection = c.id
WHERE v.group = ?", array($groupid));
if ($templates) {
require_once('collection.php');
foreach ($templates as $template) {
Collection::create_from_template(array('group' => $new_groupid), $template->id, null, false, true);
}
}
db_commit();
$SESSION->add_ok_msg(get_string('groupsaved', 'group'));
// now return to somewhere useful
switch ($return) {
case 'adminlist':
$path = get_config('wwwroot') . 'admin/groups/groups.php';
break;
case 'mylist':
$path = get_config('wwwroot') . 'groups/mygroups.php';
break;
default:
$path = get_config('wwwroot') . 'group/view.php?id=' . $new_groupid;
}
redirect($path);
}
/**
* Generates a name for a newly created group
* @param string $name The name of the group
* @return string The name with extension added, eg 'Mygroup v.2'
*/
function new_group_name($name) {
$extText = get_string('version.', 'mahara');
$temptitle = preg_split('/ '. $extText . '[0-9]$/', $name);
$title = $temptitle[0];
$taken = get_column_sql("SELECT name FROM {group} WHERE name LIKE ? || '%'", array($title));
$ext = '';
$i = 1;
if ($taken) {
while (in_array($title . $ext, $taken)) {
$ext = ' ' . $extText . ++$i;
}
}
return $title . $ext;
}
......@@ -21,6 +21,9 @@
<a class="btn btn-default btn-sm" title="{str tag="exportgroupmembershipscsv" section="admin"}" href="{$WWWROOT}download.php?type=groupmembership&groupid={$group->id}">
<span class="icon icon-users icon-lg" role="presentation" aria-hidden="true"></span><span class="sr-only">{str(tag=exportgroupmembershipscsvspecific section=admin arg1=$group->name)|escape:html|safe}</span>
</a>
<a class="btn btn-default btn-sm" title="{str tag="copy"}" href="{$WWWROOT}group/copy.php?id={$group->id}&return=adminlist">
<span class="icon icon-clone icon-lg" role="presentation" aria-hidden="true"></span><span class="sr-only">{str(tag=copygroup section=group arg1=$group->name)|escape:html|safe}</span>
</a>
<a class="btn btn-default btn-sm" title="{str tag="delete"}" href="{$WWWROOT}admin/groups/delete.php?id={$group->id}">
<span class="icon icon-trash text-danger icon-lg" role="presentation" aria-hidden="true"></span><span class="sr-only">{str(tag=deletespecific arg1=$group->name)|escape:html|safe}</span>
</a>
......
......@@ -33,8 +33,13 @@
<a href="{$WWWROOT}group/edit.php?id={$group->id}" title="{str(tag=editspecific arg1=$group->name)|escape:html|safe} {str tag=settings}" class="btn btn-default">
<span class="icon icon-cog text-default" role="presentation" aria-hidden="true"></span>
<span class="btn-title">{str tag=settings}</span>
<span class="sr-only">{str(tag=editspecific arg1=$group->name)|escape:html|safe}</span>
<span class="btn-title">{str tag=settings}</span>
<span class="sr-only">{str(tag=editspecific arg1=$group->name)|escape:html|safe}</span>
</a>
<a href="{$WWWROOT}group/copy.php?id={$group->id}&return=mygroups" title="{str(tag=copygroup section=group arg1=$group->name)|escape:html|safe}" class="btn btn-default">
<span class="icon icon-clone text-default" role="presentation" aria-hidden="true"></span>
<span class="btn-title">{str tag=copy}</span>
<span class="sr-only">{str(tag=copygroup section=group arg1=$group->name)|escape:html|safe}</span>
</a>
<a href="{$WWWROOT}group/delete.php?id={$group->id}" title="{str(tag=deletespecific arg1=$group->name)|escape:html|safe}" class="btn btn-default">
<span class="icon icon-trash text-danger" role="presentation" aria-hidden="true"></span>
......
......@@ -26,4 +26,5 @@ Scenario: Open badges block
And I wait "5" seconds
Then I should see "Your email is not found in the service"
And I press "Save"
And I wait "1" seconds
Then I should see "No public badge collections/badges found."
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment