Commit 85432b09 authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review
Browse files

Merge changes Iecdde535,Ibd74d1bd

* changes:
  Bug 1594579: Copy view artefacts only once
  Bug 1594579: Allowing a group to be duplicated
parents aec9fbd0 baac44f1
......@@ -601,13 +601,13 @@ class ArtefactTypeBlog extends ArtefactType {
$groupid = $view->get('group');
$institution = $view->get('institution');
if ($groupid || $institution) {
$SESSION->add_ok_msg(get_string('copiedblogpoststonewjournal', 'collection'));
$SESSION->add_msg_once(get_string('copiedblogpoststonewjournal', 'collection'), 'ok', true, 'messages');
}
else {
try {
$user = get_user($view->get('owner'));
set_account_preference($user->id, 'multipleblogs', 1);
$SESSION->add_ok_msg(get_string('copiedblogpoststonewjournal', 'collection'));
$SESSION->add_msg_once(get_string('copiedblogpoststonewjournal', 'collection'), 'ok', true, 'messages');
}
catch (Exception $e) {
$SESSION->add_error_msg(get_string('unabletosetmultipleblogs', 'error', $user->username, $viewid, get_config('wwwroot') . 'account/index.php'), false);
......
......@@ -227,6 +227,31 @@ class Session {
$this->__unset($key);
}
/**
* Checks that a successful message is only added once
*
* @param string $message The message to add
* @param boolean $escape Whether to HTML escape the message
* @param string $placement Place for messages to appear on page (See render_messages()
* for information about placement options)
*/
public function add_msg_once($message, $type, $escape=true, $placement='messages') {
$this->ensure_session();
if ($escape) {
$message = self::escape_message($message);
}
$msgs = $this->get('messages');
foreach ($msgs as $msg) {
if ($msg ['msg'] == $message && $msg['type'] == $type && $msg['placement'] == $placement) {
// msg exists
$this->ro_session();
return;
}
}
$typestr = 'add_' . $type . '_msg';
$this->$typestr($message, $escape=true, $placement='messages');
$this->ro_session();
}
/**
* Adds a message that indicates something was successful
*
......
......@@ -511,13 +511,13 @@ class User {
if (is_null($systemprofileviewid)) {
$systemprofileviewid = get_field('view', 'id', 'institution', 'mahara', 'template', View::SITE_TEMPLATE, 'type', 'profile');
}
$artefactcopies = array();
list($view) = View::create_from_template(array(
'owner' => $this->get('id'),
'title' => get_field('view', 'title', 'id', $systemprofileviewid),
'description' => get_string('profiledescription'),
'type' => 'profile',
), $systemprofileviewid, $this->get('id'), false);
), $systemprofileviewid, $this->get('id'), false, false, $artefactcopies);
// Set view access
$access = array(
......@@ -565,13 +565,13 @@ class User {
if (is_null($systemdashboardviewid)) {
$systemdashboardviewid = get_field('view', 'id', 'institution', 'mahara', 'template', View::SITE_TEMPLATE, 'type', 'dashboard');
}
$artefactcopies = array();
list($view) = View::create_from_template(array(
'owner' => $this->get('id'),
'title' => get_field('view', 'title', 'id', $systemdashboardviewid),
'description' => get_string('dashboarddescription'),
'type' => 'dashboard',
), $systemdashboardviewid, $this->get('id'), false);
), $systemdashboardviewid, $this->get('id'), false, false, $artefactcopies);
db_commit();
......@@ -1315,13 +1315,14 @@ class User {
}
db_begin();
$artefactcopies = array();
foreach ($templateids as $tid) {
View::create_from_template(array(
'owner' => $this->get('id'),
'title' => $views[$tid]->title,
'description' => $views[$tid]->description,
'type' => $views[$tid]->type == 'profile' && $checkviewaccess ? 'portfolio' : $views[$tid]->type,
), $tid, $this->get('id'), $checkviewaccess);
), $tid, $this->get('id'), $checkviewaccess, false, $artefactcopies);
}
db_commit();
}
......
<?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';
......
......@@ -281,6 +281,7 @@ class Collection {
$views = $colltemplate->get('views');
$copyviews = array();
$artefactcopies = array();
foreach ($views['views'] as $v) {
$values = array(
'new' => true,
......@@ -289,7 +290,7 @@ class Collection {
'institution' => isset($data->institution) ? $data->institution : null,
'usetemplate' => $v->view
);
list($view, $template, $copystatus) = View::create_from_template($values, $v->view, $userid, $checkaccess, $titlefromtemplate);
list($view, $template, $copystatus) = View::create_from_template($values, $v->view, $userid, $checkaccess, $titlefromtemplate, $artefactcopies);
if (isset($copystatus['quotaexceeded'])) {
$SESSION->clear('messages');
return array(null, $colltemplate, array('quotaexceeded' => true));
......
......@@ -462,7 +462,7 @@ function group_create($data) {
}
// Copy views for the new group
$templates = get_column('view_autocreate_grouptype', 'view', 'grouptype', $data['grouptype']);
$artefactcopies = array();
$templates = get_records_sql_array("
SELECT v.id, v.title, v.description
FROM {view} v
......@@ -477,7 +477,7 @@ function group_create($data) {
'group' => $id,
'title' => $template->title,
'description' => $template->description,
), $template->id, null, false);
), $template->id, null, false, false, $artefactcopies);
$view->set_access(array(array(
'type' => 'group',
'id' => $id,
......@@ -511,7 +511,7 @@ function group_create($data) {
'title' => $template->get('title'),
'description' => $template->get('description'),
'type' => 'grouphomepage',
), $t->id, 0, false);
), $t->id, 0, false, false, $artefactcopies);
}
else {
throw new NotFoundException("group_create: group homepage is not found");
......@@ -2751,3 +2751,176 @@ 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
$artefactcopies = array();
$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, false, $artefactcopies);
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;
}
......@@ -349,13 +349,15 @@ class View {
* @param int $userid The user who has issued the command to create the
* view. See View::_create
* @param int $checkaccess Whether to check that the user can see the view before copying it
* @param bool $titlefromtemplate Use the default title supplied by template
* @param array $artefactcopies The mapping between old artefact ids and new ones (created in blockinstance copy)
* @return array A list consisting of the new view, the template view and
* information about the copy - i.e. how many blocks and
* artefacts were copied
* @throws SystemException under various circumstances, see the source for
* more information
*/
public static function create_from_template($viewdata, $templateid, $userid=null, $checkaccess=true, $titlefromtemplate=false) {
public static function create_from_template($viewdata, $templateid, $userid=null, $checkaccess=true, $titlefromtemplate=false, &$artefactcopies) {
if (is_null($userid)) {
global $USER;
$userid = $USER->get('id');
......@@ -401,7 +403,7 @@ class View {
$view->urlid = self::new_urlid($view->urlid, (object)$viewdata);
try {
$copystatus = $view->copy_contents($template);
$copystatus = $view->copy_contents($template, $artefactcopies);
}
catch (QuotaExceededException $e) {
db_rollback();
......@@ -5446,8 +5448,8 @@ class View {
}
public function copy_contents($template) {
$artefactcopies = array(); // Correspondence between original artefact ids and id of the copy
public function copy_contents($template, &$artefactcopies) {
$this->set('numrows', $template->get('numrows'));
$this->set('layout', $template->get('layout'));
if ($template->get('owner') == 0
......@@ -6488,7 +6490,8 @@ function createview_submit(Pieform $form, $values) {
else if (isset($values['usetemplate'])) {
$templateid = $values['usetemplate'];
unset($values['usetemplate']);
list($view, $template, $copystatus) = View::create_from_template($values, $templateid);
$artefactcopies = array();
list($view, $template, $copystatus) = View::create_from_template($values, $templateid, null, true, false, $artefactcopies);
if (isset($copystatus['quotaexceeded'])) {
$SESSION->add_error_msg(get_string('viewcopywouldexceedquota', 'view'));
redirect(get_config('wwwroot') . 'view/choosetemplate.php');
......@@ -6503,7 +6506,8 @@ function createview_submit(Pieform $form, $values) {
// Use the site default portfolio page to create a new page
$sitedefaultviewid = get_field('view', 'id', 'institution', 'mahara', 'template', View::SITE_TEMPLATE, 'type', 'portfolio');
if (!empty($sitedefaultviewid)) {
list($view, $template, $copystatus) = View::create_from_template($values, $sitedefaultviewid);
$artefactcopies = array();
list($view, $template, $copystatus) = View::create_from_template($values, $sitedefaultviewid, null, true, false, $artefactcopies);
if (isset($copystatus['quotaexceeded'])) {
$SESSION->add_error_msg(get_string('viewcreatewouldexceedquota', 'view'));
redirect(get_config('wwwroot') . 'view/index.php');
......@@ -6563,7 +6567,8 @@ function copyview($id, $istemplate = false, $groupid = null, $collectionid = nul
redirect(get_config('wwwroot') . 'collection/edit.php?copy=1&id=' . $collection->get('id'));
}
else {
list($view, $template, $copystatus) = View::create_from_template($values, $id);
$artefactcopies = array();
list($view, $template, $copystatus) = View::create_from_template($values, $id, null, true, false, $artefactcopies);
if (isset($copystatus['quotaexceeded'])) {
$SESSION->add_error_msg(get_string('viewcopywouldexceedquota', 'view'));
redirect(get_config('wwwroot') . 'view/view.php?id=' . $id);
......
......@@ -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."
Supports Markdown
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