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

Merge changes...

Merge changes Ib67a4adf,I2354cdcf,Iecf288d4,I961671d7,I02760d10,Idb307371,Ib705b8fc,Ic6bcfab3,If66abd5b,Ia46c3c52,I847aa583,Ide4f33ab,I7b2143ac,I14c6af22,I3841a74d

* changes:
  Group collections and views in the submission drop-down (bug #786389)
  Add optgroups to pieform select element
  Use View::get_views_and_collections for submission lists (bug #786389)
  Filter by submitted views in View::get_views_and_collections
  Show submission information on collection index page (bug #786389)
  Disallow editing and deletion of submitted collections (bug #786389)
  Get the details of the entity a collection is submitted to
  Modify release form to release entire collections (bug #786389)
  Handle collection submissions in view/submit.php (bug #786389)
  Add a function to release a submitted collection (bug #786389)
  Allow required activity parameters to be specified as strings
  Separate db-specific parts from View::release
  Deal with collections in submission forms (bug #786389)
  Add submission properties to Collection class (bug #786389)
  Add submission fields to collection table (bug #786389)
parents 1c6a7ff5 613a14eb
......@@ -79,11 +79,11 @@ class PluginBlocktypeGroupViews extends SystemBlocktype {
if (!empty($configdata['showsharedviews']) && isset($data['sharedviews'])) {
$dwoo->assign('sharedviews', $data['sharedviews']->data);
}
if (isset($data['allsubmittedviews'])) {
$dwoo->assign('allsubmittedviews', $data['allsubmittedviews']);
if (isset($data['allsubmitted'])) {
$dwoo->assign('allsubmitted', $data['allsubmitted']);
}
if (isset($data['mysubmittedviews'])) {
$dwoo->assign('mysubmittedviews', $data['mysubmittedviews']);
if (isset($data['mysubmitted'])) {
$dwoo->assign('mysubmitted', $data['mysubmitted']);
}
if (!$editing && isset($data['group_view_submission_form'])) {
$dwoo->assign('group_view_submission_form', $data['group_view_submission_form']);
......@@ -158,11 +158,12 @@ class PluginBlocktypeGroupViews extends SystemBlocktype {
if (group_user_can_assess_submitted_views($group->id, $USER->get('id'))) {
// Display a list of views submitted to the group
$data['allsubmittedviews'] = View::get_submitted_views($group->id);
list($collections, $views) = View::get_views_and_collections(null, null, null, null, false, $group->id);
$data['allsubmitted'] = array_merge(array_values($collections), array_values($views));
}
}
if ($group->submittableto && ($userviewdata = View::get_user_views())) {
if ($group->submittableto) {
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.
......@@ -170,18 +171,10 @@ class PluginBlocktypeGroupViews extends SystemBlocktype {
// Display a list of views this user has submitted to this group, and a submission
// form containing drop-down of their unsubmitted views.
$data['mysubmittedviews'] = View::get_submitted_views($group->id, $USER->get('id'));
if (!empty($data['mysubmittedviews'])) {
foreach ($data['mysubmittedviews'] as &$v) {
if ($v['submittedtime']) {
$v['submittedtime'] = format_date($v['submittedtime']);
}
}
}
$data['group_view_submission_form'] = group_view_submission_form($group->id, $userviewdata);
list($collections, $views) = View::get_views_and_collections($USER->get('id'), null, null, null, false, $group->id);
$data['mysubmitted'] = array_merge(array_values($collections), array_values($views));
$data['group_view_submission_form'] = group_view_submission_form($group->id);
}
$data['group'] = $group;
return $data;
......
......@@ -50,19 +50,19 @@
{/if}
{if $mysubmittedviews || $group_view_submission_form}
{if $mysubmitted || $group_view_submission_form}
<div class="groupviewsection">
{if $group_view_submission_form}
<h5>{str tag="submitaviewtogroup" section="view"}</h5>
<h5>{str tag="submittogroup" section="view"}</h5>
{/if}
<table class="fullwidth listing">
{if $mysubmittedviews}
{foreach from=$mysubmittedviews item=view}
{if $mysubmitted}
{foreach from=$mysubmitted item=item}
<tr class="{cycle values='r0,r1'}"><td class="submittedform">
{if $view.submittedtime}
{str tag=youhavesubmittedon section=view arg1=$view.fullurl arg2=$view.title arg3=$view.submittedtime}
{if $item.submittedtime}
{str tag=youhavesubmittedon section=view arg1=$item.url arg2=$item.name arg3=$item.submittedtime|format_date}
{else}
{str tag=youhavesubmitted section=view arg1=$view.fullurl arg2=$view.title}
{str tag=youhavesubmitted section=view arg1=$item.url arg2=$item.name}
{/if}
</td></tr>
{/foreach}
......@@ -76,21 +76,21 @@
</div>
{/if}
{if $allsubmittedviews}
{if $allsubmitted}
<div class="groupviewsection">
<table class="fullwidth listing">
<tr>
<td><h5>{str tag="viewssubmittedtogroup" section="view"}</h5></td>
<td><h5>{str tag="submissionstogroup" section="view"}</h5></td>
<th>{str tag=timeofsubmission section=view}</th>
</tr>
{foreach from=$allsubmittedviews item=view}
{foreach from=$allsubmitted item=item}
<tr class="{cycle values='r0,r1'}">
<td>
<strong><a href="{$view.fullurl}">{$view.title|str_shorten_text:60:true}</a></strong>
<div><a href="{profile_url($view.user)}">{$view.sharedby}</a></div>
<strong><a href="{$item.url}">{$item.name|str_shorten_text:60:true}</a></strong>
<div><a href="{$item.ownerurl}">{$item.ownername}</a></div>
</td>
<td>
<div class="postedon nowrap">{$view.submittedtime|format_date}</div>
<div class="postedon nowrap">{$item.submittedtime|format_date}</div>
</td>
</tr>
{/foreach}
......
......@@ -44,6 +44,12 @@ if (!$USER->can_edit_collection($collection)) {
$SESSION->add_error_msg(get_string('cantdeletecollection', 'collection'));
redirect('/collection/');
}
if ($collection->is_submitted()) {
$submitinfo = $collection->submitted_to();
throw new AccessDeniedException(get_string('canteditsubmitted', 'collection', $submitinfo->name));
}
$form = pieform(array(
'name' => 'deletecollection',
'renderer' => 'div',
......
......@@ -44,6 +44,10 @@ if (!$USER->can_edit_collection($collection)) {
$SESSION->add_error_msg(get_string('canteditdontown', 'collection'));
redirect('/collection/');
}
if ($collection->is_submitted()) {
$submitinfo = $collection->submitted_to();
throw new AccessDeniedException(get_string('canteditsubmitted', 'collection', $submitinfo->name));
}
// if not a new collection
if (!$new) {
......
......@@ -47,6 +47,10 @@ if (!$USER->can_edit_collection($collection)) {
$SESSION->add_error_msg(get_string('canteditdontown', 'collection'));
redirect('/collection/');
}
if ($collection->is_submitted()) {
$submitinfo = $collection->submitted_to();
throw new AccessDeniedException(get_string('canteditsubmitted', 'collection', $submitinfo->name));
}
define('TITLE', $collection->get('name') . ': ' . get_string('editviews', 'collection'));
......
......@@ -144,7 +144,7 @@ $string['institutioninvitemessage'] = 'You can confirm your membership of this i
$string['deleteallnotifications'] = 'Delete all notifications';
$string['reallydeleteallnotifications'] = 'Are you sure you want to delete all your notifications of this activity type?';
$string['viewsubmittedsubject'] = 'Page submitted to %s';
$string['viewsubmittedmessage'] = '%s has submitted their page "%s" to %s';
$string['viewsubmittedsubject1'] = 'Submission to %s';
$string['viewsubmittedmessage1'] = '%s has submitted "%s" to %s';
$string['adminnotificationerror'] = 'User notification error was probably caused by your server configuration.';
......@@ -42,6 +42,7 @@ $string['addviewstocollection'] = 'Add pages to collection';
$string['back'] = 'Back';
$string['cantdeletecollection'] = 'You cannot delete this collection.';
$string['canteditdontown'] = 'You cannot edit this collection because you do not own it.';
$string['canteditsubmitted'] = 'You can\'t edit this collection because it has been submitted for assessment to %s. You will have to wait until a tutor releases it.';
$string['collection'] = 'collection';
$string['Collection'] = 'Collection';
$string['collections'] = 'Collections';
......
......@@ -143,6 +143,7 @@ $string['memberrequests'] = 'Membership requests';
$string['declinerequest'] = 'Decline request';
$string['submittedviews'] = 'Submitted pages';
$string['releaseview'] = 'Release page';
$string['releasecollection'] = 'Release collection';
$string['invite'] = 'Invite';
$string['remove'] = 'Remove';
$string['updatemembership'] = 'Update membership';
......@@ -150,7 +151,10 @@ $string['memberchangefailed'] = 'Failed to update some membership information';
$string['memberchangesuccess'] = 'Membership status changed successfully';
$string['viewreleasedsubject'] = 'Your page "%s" has been released from %s by %s';
$string['viewreleasedmessage'] = 'Your page "%s" has been released from %s by %s';
$string['collectionreleasedsubject'] = 'Your collection "%s" has been released from %s by %s';
$string['collectionreleasedmessage'] = 'Your collection "%s" has been released from %s by %s';
$string['viewreleasedsuccess'] = 'Page was released successfully';
$string['collectionreleasedsuccess'] = 'Collection released successfully';
$string['leavegroup'] = 'Leave this group';
$string['joingroup'] = 'Join this group';
$string['requestjoingroup'] = 'Request to join this group';
......
......@@ -66,6 +66,7 @@ $string['viewdeleted'] = 'Page deleted';
$string['viewsubmitted'] = 'Page submitted';
$string['deletethisview'] = 'Delete this page';
$string['submitthisviewto'] = 'Submit this page to';
$string['submitthiscollectionto'] = 'Submit this collection to';
$string['forassessment'] = 'for assessment';
$string['accessfromdate2'] = 'Nobody else can see this page before %s';
$string['accessuntildate2'] = 'Nobody else can see this page after %s';
......@@ -78,6 +79,8 @@ $string['View'] = 'Page';
$string['Views'] = 'Pages';
$string['viewsubmittedtogroup'] = 'This page has been submitted to <a href="%s">%s</a>';
$string['viewsubmittedtogroupon'] = 'This page was submitted to <a href="%s">%s</a> on %s';
$string['collectionsubmittedtogroup'] = 'This collection has been submitted to <a href="%s">%s</a>';
$string['collectionsubmittedtogroupon'] = 'This collection was submitted to <a href="%s">%s</a> on %s';
$string['nobodycanseethisview2'] = 'Only you can see this page';
$string['noviews'] = 'No pages.';
$string['nviews'] = array(
......@@ -91,8 +94,8 @@ $string['youhaveviews'] = 'You have %s pages.';
$string['viewsownedbygroup'] = 'Pages owned by this group';
$string['viewssharedtogroup'] = 'Pages shared with this group';
$string['viewssharedtogroupbyothers'] = 'Pages shared with this group by others';
$string['viewssubmittedtogroup'] = 'Pages submitted to this group';
$string['submitaviewtogroup'] = 'Submit a page to this group';
$string['submissionstogroup'] = 'Submissions to this group';
$string['submittogroup'] = 'Submit a page or collection to this group';
$string['youhavesubmitted'] = 'You have submitted <a href="%s">%s</a> to this group';
$string['youhavesubmittedon'] = 'You submitted <a href="%s">%s</a> to this group on %s';
$string['listedinpages'] = 'Listed in pages';
......@@ -162,10 +165,14 @@ $string['moreoptions'] = 'Advanced options';
$string['moreinstitutions'] = 'More institutions';
$string['allviews'] = 'All pages';
$string['submitviewconfirm'] = 'If you submit \'%s\' to \'%s\' for assessment, you will not be able to edit this page until your tutor has finished marking it. Are you sure you want to submit this page now?';
$string['submitconfirm'] = 'If you submit \'%s\' to %s for assessment, you will not be able to edit its contents until your tutor has finished marking it. Are you sure you want to submit now?';
$string['viewsubmitted'] = 'Page submitted';
$string['collectionsubmitted'] = 'Collection submitted';
$string['viewsalreadysubmitted'] = 'Some pages in this collection have already been submitted:<br>%s<br>You cannot submit the collection until they have been released.';
$string['submitviewtogroup'] = 'Submit \'%s\' to \'%s\' for assessment';
$string['cantsubmitviewtogroup'] = 'You cannot submit this page to this group for assessment';
$string['cantsubmitcollectiontogroup'] = 'You cannot submit this collection';
$string['cantsubmittogroup'] = 'You cannot submit to this group';
$string['cantdeleteview'] = 'You cannot delete this page';
$string['deletespecifiedview'] = 'Delete page "%s"';
......
......@@ -358,7 +358,10 @@ abstract class ActivityType {
private function ensure_parameters() {
foreach ($this->get_required_parameters() as $param) {
if (!isset($this->{$param})) {
throw new ParamOutOfRangeException(get_string('missingparam', 'activity', $param, $this->get_type()));
// Allow some string parameters to be specified in $this->strings
if (!in_array($param, array('subject', 'message', 'urltext')) || empty($this->strings->{$param}->key)) {
throw new ParamOutOfRangeException(get_string('missingparam', 'activity', $param, $this->get_type()));
}
}
}
}
......
......@@ -36,6 +36,9 @@ class Collection {
private $mtime;
private $ctime;
private $navigation;
private $submittedgroup;
private $submittedhost;
private $submittedtime;
private $views;
public function __construct($id=0, $data=null) {
......@@ -151,7 +154,7 @@ class Collection {
$fordb = new StdClass;
foreach (get_object_vars($this) as $k => $v) {
$fordb->{$k} = $v;
if (in_array($k, array('mtime', 'ctime')) && !empty($v)) {
if (in_array($k, array('mtime', 'ctime', 'submittedtime')) && !empty($v)) {
$fordb->{$k} = db_format_timestamp($v);
}
}
......@@ -291,7 +294,7 @@ class Collection {
public static function get_mycollections_data($offset=0, $limit=10) {
global $USER;
($data = get_records_sql_array("
($data = get_records_sql_assoc("
SELECT c.id, c.description, c.name
FROM {collection} c
WHERE c.owner = ?
......@@ -299,9 +302,11 @@ class Collection {
LIMIT ? OFFSET ?", array($USER->get('id'), $limit, $offset)))
|| ($data = array());
self::add_submission_info($data);
$result = (object) array(
'count' => count_records('collection', 'owner', $USER->get('id')),
'data' => $data,
'data' => array_values($data),
'offset' => $offset,
'limit' => $limit,
);
......@@ -309,6 +314,47 @@ class Collection {
return $result;
}
private static function add_submission_info(&$data) {
if (empty($data)) {
return;
}
$records = get_records_sql_assoc('
SELECT c.id, c.submittedgroup, c.submittedhost, ' . db_format_tsfield('submittedtime') . ',
sg.name AS groupname, sg.urlid, sh.name AS hostname
FROM {collection} c
LEFT JOIN {group} sg ON c.submittedgroup = sg.id
LEFT JOIN {host} sh ON c.submittedhost = sh.wwwroot
WHERE c.id IN (' . join(',', array_fill(0, count($data), '?')) . ')
AND (c.submittedgroup IS NOT NULL OR c.submittedhost IS NOT NULL)',
array_keys($data)
);
if (empty($records)) {
return;
}
foreach ($records as $r) {
if (!empty($r->submittedgroup)) {
$groupdata = (object) array(
'id' => $r->submittedgroup,
'name' => $r->groupname,
'urlid' => $r->urlid,
'time' => $r->submittedtime,
);
$groupdata->url = group_homepage_url($groupdata);
$data[$r->id]->submitinfo = $groupdata;
}
else if (!empty($r->submittedhost)) {
$data[$r->id]->submitinfo = (object) array(
'name' => $r->hostname,
'url' => $r->submittedhost,
'time' => $r->submittedtime,
);
}
}
}
/**
* Gets the fields for the new/edit collection form
* - populates the fields with collection data if it is an edit
......@@ -585,4 +631,189 @@ class Collection {
}
throw new SystemException("View::owner_sql: Passed object did not have an institution, group or owner field");
}
/**
* Makes a URL for a collection
*
* @param bool $full return a full url
* @param bool $useid ignore clean url settings and always return a url with an id in it
*
* @return string
*/
public function get_url($full=true, $useid=false) {
global $USER;
$views = $this->views();
if (!empty($views)) {
$v = new View(0, $views['views'][0]);
$v->set('dirty', false);
return $v->get_url($full, $useid);
}
log_warn("Attempting to get url for an empty collection");
if ($this->owner === $USER->get('id')) {
$url = 'collection/views.php?id=' . $this->id;
}
else {
$url = '';
}
if ($full) {
$url = get_config('wwwroot') . $url;
}
return $url;
}
/**
* Release a submitted collection
*
* @param object $releaseuser The user releasing the collection
*/
public function release($releaseuser=null) {
if (!$this->is_submitted()) {
throw new ParameterException("Collection with id " . $this->id . " has not been submitted");
}
// One day there might be group and institution collections, so be safe
if (empty($this->owner)) {
throw new ParameterException("Collection with id " . $this->id . " has no owner");
}
$viewids = $this->get_viewids();
db_begin();
execute_sql('
UPDATE {collection}
SET submittedgroup = NULL, submittedhost = NULL, submittedtime = NULL
WHERE id = ?',
array($this->id)
);
View::_db_release($viewids, $this->owner, $this->submittedgroup);
db_commit();
$releaseuser = optional_userobj($releaseuser);
$releaseuserdisplay = display_name($releaseuser, $this->owner);
$submitinfo = $this->submitted_to();
require_once('activity.php');
activity_occurred(
'maharamessage',
array(
'users' => array($this->get('owner')),
'strings' => (object) array(
'subject' => (object) array(
'key' => 'collectionreleasedsubject',
'section' => 'group',
'args' => array($this->name, $submitinfo->name, $releaseuserdisplay),
),
'message' => (object) array(
'key' => 'collectionreleasedmessage',
'section' => 'group',
'args' => array($this->name, $submitinfo->name, $releaseuserdisplay),
),
),
'url' => $this->get_url(false),
'urltext' => $this->name,
)
);
}
public function get_viewids() {
$ids = array();
$viewdata = $this->views();
if (!empty($viewdata['views'])) {
foreach ($viewdata['views'] as $v) {
$ids[] = $v->id;
}
}
return $ids;
}
public function is_submitted() {
return $this->submittedgroup || $this->submittedhost;
}
public function submitted_to() {
if ($this->submittedgroup) {
$record = get_record('group', 'id', $this->submittedgroup, null, null, null, null, 'id, name, urlid');
$record->url = group_homepage_url($record);
}
else if ($this->submittedhost) {
$record = get_record('host', 'wwwroot', $this->submittedhost, null, null, null, null, 'wwwroot, name');
$record->url = $record->wwwroot;
}
else {
throw new SystemException("Collection with id " . $this->id . " has not been submitted");
}
return $record;
}
public function submit($group) {
global $USER;
if ($this->is_submitted()) {
throw new SystemException('Attempting to submit a submitted collection');
}
$viewids = $this->get_viewids();
$idstr = join(',', array_map('intval', $viewids));
// Check that none of the views is submitted to some other group. This is bound to happen to someone,
// because collection submission is being introduced at a time when it is still possible to submit
// individual views in a collection.
$submittedtitles = get_column_sql("
SELECT title FROM {view}
WHERE id IN ($idstr) AND (submittedhost IS NOT NULL OR (submittedgroup IS NOT NULL AND submittedgroup != ?))",
array($group->id)
);
if (!empty($submittedtitles)) {
die_info(get_string('viewsalreadysubmitted', 'view', implode('<br>', $submittedtitles)));
}
$group->roles = get_column('grouptype_roles', 'role', 'grouptype', $group->grouptype, 'see_submitted_views', 1);
db_begin();
View::_db_submit($viewids, $group);
$this->set('submittedgroup', $group->id);
$this->set('submittedhost', null);
$this->set('submittedtime', time());
$this->commit();
db_commit();
activity_occurred(
'groupmessage',
array(
'group' => $group->id,
'roles' => $group->roles,
'url' => $this->get_url(false),
'strings' => (object) array(
'urltext' => (object) array(
'key' => 'Collection',
'section' => 'collection',
),
'subject' => (object) array(
'key' => 'viewsubmittedsubject1',
'section' => 'activity',
'args' => array($group->name),
),
'message' => (object) array(
'key' => 'viewsubmittedmessage1',
'section' => 'activity',
'args' => array(
display_name($USER, null, false, true),
$this->name,
$group->name,
),
),
),
)
);
}
}
......@@ -912,10 +912,15 @@
<FIELD NAME="name" TYPE="text" NOTNULL="true" />
<FIELD NAME="description" TYPE="text" NOTNULL="false" />
<FIELD NAME="navigation" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1"/>
<FIELD NAME="submittedgroup" TYPE="int" LENGTH="10" NOTNULL="false" />
<FIELD NAME="submittedhost" TYPE="char" LENGTH="255" NOTNULL="false" />
<FIELD NAME="submittedtime" TYPE="datetime" NOTNULL="false" />
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
<KEY NAME="usrfk" TYPE="foreign" FIELDS="owner" REFTABLE="usr" REFFIELDS="id" />
<KEY NAME="submittedgroupfk" TYPE="foreign" FIELDS="submittedgroup" REFTABLE="group" REFFIELDS="id" />
<KEY NAME="submittedhostfk" TYPE="foreign" FIELDS="submittedhost" REFTABLE="host" REFFIELDS="wwwroot" />
</KEYS>
</TABLE>
<TABLE NAME="collection_view">
......
......@@ -2923,5 +2923,30 @@ function xmldb_core_upgrade($oldversion=0) {
add_index($table, $index);
}
if ($oldversion < 2012060100) {
// Collection submission
$table = new XMLDBTable('collection');
$field = new XMLDBField('submittedgroup');
$field->setAttributes(XMLDB_TYPE_INTEGER, 10);
add_field($table, $field);
$field = new XMLDBField('submittedhost');
$field->setAttributes(XMLDB_TYPE_CHAR, 255);
add_field($table, $field);
$field = new XMLDBField('submittedtime');
$field->setAttributes(XMLDB_TYPE_DATETIME);
add_field($table, $field);
$key = new XMLDBKey('submittedgroupfk');
$key->setAttributes(XMLDB_KEY_FOREIGN, array('submittedgroup'), 'group', array('id'));
add_key($table, $key);
$key = new XMLDBKey('submittedhostfk');
$key->setAttributes(XMLDB_KEY_FOREIGN, array('submittedhost'), 'host', array('wwwroot'));
add_key($table, $key);
}
return $status;
}
......@@ -1202,16 +1202,49 @@ function group_removeuser_submit(Pieform $form, $values) {
/**
* Form for submitting views to a group
*/
function group_view_submission_form($groupid, $viewdata) {
$options = array();
foreach ($viewdata as $view) {
if (empty($view->submittedgroup) && empty($view->submittedhost)) {
$options[$view->id] = $view->title;
function group_view_submission_form($groupid) {
global $USER;
list($collections, $views) = View::get_views_and_collections($USER->get('id'));
$viewoptions = $collectionoptions = array();
foreach ($collections as $c) {
if (empty($c['submittedgroup']) && empty($c['submittedhost'])) {
$collectionoptions['c:' . $c['id']] = $c['name'];
}
}
foreach ($views as $v) {
if ($v['type'] != 'profile' && empty($v['submittedgroup']) && empty($v['submittedhost'])) {