Commit 4b5601ae authored by Melissa Draper's avatar Melissa Draper
Browse files

Participation reports for groups (bug #1018711)



This adds a new page to the groups subnav menu where participation
in the group by members and non-members can be viewed by the people
who manage the group.

Change-Id: Icd0603b2bb0f448c0523e8ae12c2fb7c8a5e3d4d
Signed-off-by: default avatarMelissa Draper <melissa@catalyst.net.nz>
parent f9e5f92b
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2012 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 Melissa Draper <melissa@catalyst.net.nz>, Catalyst IT Ltd
*
*/
define('INTERNAL', 1);
require(dirname(dirname(__FILE__)) . '/init.php');
require_once('view.php');
require_once('group.php');
safe_require('artefact', 'comment');
define('TITLE', get_string('report', 'group'));
define('MENUITEM', 'groups/report');
define('GROUP', param_integer('group'));
$wwwroot = get_config('wwwroot');
$needsubdomain = get_config('cleanurlusersubdomains');
$setlimit = true;
$limit = param_integer('limit', 10);
$offset = param_integer('offset', 0);
$sort = param_variable('sort', 'title');
$direction = param_variable('direction', 'asc');
$group = group_current_group();
$role = group_user_access($group->id);
if (!group_role_can_access_report($group, $role)) {
throw new AccessDeniedException();
}
$sharedviews = View::get_sharedviews_data(0, null, $group->id);
$sharedviewscount = $sharedviews->count;
$sharedviews = $sharedviews->data;
foreach ($sharedviews as &$data) {
if (isset($data['group'])) {
$sharedviews[$id]['groupname'] = get_field('group', 'name', 'id', $data['group']);
}
$view = new View($data['id']);
$comments = ArtefactTypeComment::get_comments(0, 0, null, $view);
$extcommenters = 0;
$membercommenters = 0;
$extcomments = 0;
$membercomments = 0;
$commenters = array();
foreach ($comments->data as $c) {
if (empty($c->author)) {
if (!isset($commenters[$c->authorname])) {
$commenters[$c->authorname] = array();
}
$commenters[$c->authorname]['commenter'] = $c->authorname;
$commenters[$c->authorname]['count'] = (isset($commenters[$c->authorname]['count']) ? $commenters[$c->authorname]['count'] + 1 : 1);
if ($commenters[$c->authorname]['count'] == 1) {
$extcommenters++;
}
$extcomments++;
}
else {
if (!isset($commenters[$c->author->id])) {
$commenters[$c->author->id] = array();
}
$commenters[$c->author->id]['commenter'] = (int) $c->author->id;
$commenters[$c->author->id]['member'] = group_user_access($group->id, $c->author->id);
$commenters[$c->author->id]['count'] = (isset($commenters[$c->author->id]['count']) ? $commenters[$c->author->id]['count'] + 1 : 1);
if (empty($commenters[$c->author->id]['member'])) {
if ($commenters[$c->author->id]['count'] == 1) {
$extcommenters++;
}
$extcomments++;
}
else {
if ($commenters[$c->author->id]['count'] == 1) {
$membercommenters++;
}
$membercomments++;
}
}
}
sorttablebycolumn($commenters, 'count', 'desc');
$data['mcommenters'] = $membercommenters;
$data['ecommenters'] = $extcommenters;
$data['mcomments'] = $membercomments;
$data['ecomments'] = $extcomments;
$data['comments'] = $commenters;
$data['baseurl'] = $needsubdomain ? $view->get_url(true) : ($wwwroot . $view->get_url(false));
}
if (in_array($sort, array('title', 'sharedby', 'mcomments', 'ecomments'))) {
sorttablebycolumn($sharedviews, $sort, $direction);
}
$sharedviews = array_slice($sharedviews, $offset, $limit);
list($searchform, $groupviews, $unusedpagination) = View::views_by_owner($group->id);
$groupviews = $groupviews->data;
$groupviewscount = count($groupviews);
foreach ($groupviews as &$data) {
$view = new View($data['id']);
$comments = ArtefactTypeComment::get_comments(0, 0, null, $view);
$extcommenters = 0;
$membercommenters = 0;
$extcomments = 0;
$membercomments = 0;
$commenters = array();
foreach ($comments->data as $c) {
if (empty($c->author)) {
if (!isset($commenters[$c->authorname])) {
$commenters[$c->authorname] = array();
}
$commenters[$c->authorname]['commenter'] = $c->authorname;
$commenters[$c->authorname]['count'] = (isset($commenters[$c->authorname]['count']) ? $commenters[$c->authorname]['count'] + 1 : 1);
if ($commenters[$c->authorname]['count'] == 1) {
$extcommenters++;
}
$extcomments++;
}
else {
if (!isset($commenters[$c->author->id])) {
$commenters[$c->author->id] = array();
}
$commenters[$c->author->id]['commenter'] = (int) $c->author->id;
$commenters[$c->author->id]['member'] = group_user_access($group->id, $c->author->id);
$commenters[$c->author->id]['count'] = (isset($commenters[$c->author->id]['count']) ? $commenters[$c->author->id]['count'] + 1 : 1);
if (empty($commenters[$c->author->id]['member'])) {
if ($commenters[$c->author->id]['count'] == 1) {
$extcommenters++;
}
$extcomments++;
}
else {
if ($commenters[$c->author->id]['count'] == 1) {
$membercommenters++;
}
$membercomments++;
}
}
}
$data['id'] = (int) $data['id'];
$data['mcommenters'] = $membercommenters;
$data['ecommenters'] = $extcommenters;
$data['mcomments'] = $membercomments;
$data['ecomments'] = $extcomments;
$data['comments'] = $commenters;
$data['title'] = $data['displaytitle'];
}
if (in_array($sort, array('title', 'mcomments', 'ecomments'))) {
sorttablebycolumn($groupviews, $sort, $direction);
}
$groupviews = array_slice($groupviews, $offset, $limit);
$pagination = build_pagination(array(
'url' => get_config('wwwroot') . 'group/report.php?group=' . $group->id,
'count' => max($sharedviewscount, $groupviewscount),
'limit' => $limit,
'setlimit' => $setlimit,
'offset' => $offset,
'jumplinks' => 6,
'numbersincludeprevnext' => 2,
));
$js = <<< EOF
addLoadEvent(function () {
p = {$pagination['javascript']}
});
EOF;
$smarty = smarty(array('paginator'));
$smarty->assign('baseurl', get_config('wwwroot') . 'group/report.php?group=' . $group->id);
$smarty->assign('heading', $group->name);
$smarty->assign('sharedviews', $sharedviews);
$smarty->assign('groupviews', $groupviews);
$smarty->assign('pagination', $pagination['html']);
$smarty->assign('INLINEJAVASCRIPT', $js);
$smarty->assign('gvcount', $groupviewscount);
$smarty->assign('svcount', $sharedviewscount);
$smarty->assign('sort', $sort);
$smarty->assign('direction', $direction);
$smarty->display('group/report.tpl');
......@@ -365,3 +365,17 @@ $string['submit'] = 'Submit';
$string['allowssubmissions'] = 'Allows submissions';
$string['allowsubmissions'] = 'Allow submissions';
$string['allowssubmissionsdescription1'] = "Members can submit pages to the group that are then locked. These pages can't be edited until they are released by a group tutor or administrator.";
$string['allowssubmissionsdescription'] = 'Members can submit pages to the group';
// Group reports
$string['report'] = 'Report';
$string['grouphasntcreatedanyviewsyet'] = "This group hasn't created any pages yet.";
$string['noviewssharedwithgroupyet'] = "There are no pages shared with this group yet.";
$string['groupsharedviewsscrolled'] = "You have scrolled past the end of the shared pages list.";
$string['groupcreatedviewsscrolled'] = "You have scrolled past the end of the group's pages list.";
$string['nnonmembers'] = array(
'1 non-member',
'%s non-members',
);
$string['membercommenters'] = "Members involved";
$string['extcommenters'] = "Non-members involved";
......@@ -362,3 +362,6 @@ $string['tagsonly'] = 'Tags only';
$string['sharedviewsdescription'] = 'This page lists the most recently modified or commented on pages that have been shared with you. They may have been shared with you directly, shared with friends of the owner, or shared with one of your groups.';
$string['sharedwith'] = 'Shared with';
$string['Me'] = 'Me';
// Group reports
$string['sharedby'] = 'Shared by';
......@@ -202,6 +202,23 @@ function group_role_can_moderate_views($group, $role) {
return in_array($role, $moderatingroles[$group]);
}
/**
* Returns whether a user is allowed to see the report
*
* @param obj $group The group object
* @param str $role The role of the user
* @returns boolean
*/
function group_role_can_access_report($group, $role) {
global $USER;
if (group_user_access($group->id) && ($role == 'admin' || $USER->get('admin') || $USER->is_institutional_admin() || $USER->is_institutional_staff())) {
return true;
}
return false;
}
/**
* Returns whether a user is allowed to assess views that have been submitted
* to the given group.
......@@ -1672,6 +1689,15 @@ function group_get_menu_tabs() {
}
}
if (group_role_can_access_report($group, $role)) {
$menu['report'] = array(
'path' => 'groups/report',
'url' => 'group/report.php?group=' . $group->id,
'title' => get_string('report', 'group'),
'weight' => 70,
);
}
if (defined('MENUITEM')) {
$key = substr(MENUITEM, strlen('groups/'));
if ($key && isset($menu[$key])) {
......
......@@ -3543,3 +3543,45 @@ function generate_urlid($dirty, $default, $minlength=3, $maxlength=100) {
}
return $s;
}
/**
* Sorts an array by one of the value fields
*
* @param array $data an array of arrays
* @param string $sort a key field value of second tier array
* @param string $direction the direction of the sort
*/
function sorttablebycolumn(&$data, $sort, $direction) {
global $sortvalue;
$sortvalue = $sort;
if ($direction == 'desc') {
usort($data, 'sorttablearraydesc'); }
else {
usort($data, 'sorttablearrayasc');
}
}
/**
* Compare function for sorttablebycolumn()
* Sorts ascending.
*/
function sorttablearrayasc($a, $b) {
global $sortvalue;
if (is_string($a[$sortvalue])) {
return strcmp(strtolower($a[$sortvalue]), strtolower($b[$sortvalue]));
}
return ($a[$sortvalue] < $b[$sortvalue]) ? -1 : 1;
}
/**
* Compare function for sorttablebycolumn()
* Sorts descending
*/
function sorttablearraydesc($a, $b) {
global $sortvalue;
if (is_string($a[$sortvalue])) {
return strcmp(strtolower($b[$sortvalue]), strtolower($a[$sortvalue]));
}
return ($b[$sortvalue] < $a[$sortvalue]) ? -1 : 1;
}
......@@ -2789,3 +2789,29 @@ form#register tbody tr.checkbox td {
font-weight:normal;
margin: 0px 5px
}
/* Group reports */
table.groupviewsreport .sorted, table.sharedviewsreport .sorted {
background: url("../images/down.gif") no-repeat scroll 2px center transparent;
padding-left: 18px;
text-decoration: none;
}
table.groupviewsreport .asc, table.sharedviewsreport .asc {
background: url("../images/up.gif") no-repeat scroll 2px center transparent;
padding-left: 18px;
text-decoration: none;
}
table.groupviewsreport li, table.sharedviewsreport li {
clear: both;
}
table.groupviewsreport ul, table.sharedviewsreport ul {
margin: 0px;
}
table.groupviewsreport li span.right, table.sharedviewsreport li span.right {
float: right;
}
{include file="header.tpl"}
{if !$sharedviews && !$groupviews}
<p>{str tag=youhaventcreatedanyviewsyet section=view}</p>
{else}
<table class="fullwidth sharedviewsreport">
<thead>
<tr>
<th class="sv {if $sort == title && $direction == asc}asc{elseif $sort == title}sorted{/if}">
<a href="{$baseurl}&sort=title{if $sort == title && $direction == asc}&direction=desc{/if}">{str tag=viewssharedtogroup section=view}</a>
</th>
<th class="sb {if $sort == sharedby && $direction == asc}asc{elseif $sort == sharedby}sorted{/if}">
<a href="{$baseurl}&sort=sharedby{if $sort == sharedby && $direction == asc}&direction=desc{/if}">{str tag=sharedby section=view}</a>
</th>
<th class="mc {if $sort == mcomments && $direction == asc}asc{elseif $sort == mcomments}sorted{/if}">
<a href="{$baseurl}&sort=mcomments{if $sort == mcomments && $direction == asc}&direction=desc{/if}">{str tag=membercommenters section=group}</a>
</th>
<th class="ec {if $sort == ecomments && $direction == asc}asc{elseif $sort == ecomments}sorted{/if}">
<a href="{$baseurl}&sort=ecomments{if $sort == ecomments && $direction == asc}&direction=desc{/if}">{str tag=extcommenters section=group}</a>
</th>
</tr>
</thead>
<tbody>
{if $sharedviews}
{foreach from=$sharedviews item=view}
<tr class="{cycle values='r0,r1'}">
<td><a href="{$view.baseurl}">{$view.title}</a></td>
<td>
{if $view.owner}
<a href="{$WWWROOT}user/view.php?id={$view.owner}">{$view.user->id|display_name:null:true|escape}</a>
{elseif $view.group}
<a href="{$WWWROOT}group/view.php?id={$view.group}">{$view.groupname|escape}</a>
{elseif $view.institution}
<a href="{$WWWROOT}institution/view.php?id={$view.institution}">{$view.institution|escape}</a>
{/if}
</td>
<td>
<ul>
{foreach from=$view.comments key=commenter item=info}
{if $info.member}<li><a href="{$WWWROOT}user/view.php?id={$info.commenter}">{$info.commenter|display_name:null:true|escape}</a><span class="right">{$info.count}</span></li>{/if}
{/foreach}
</ul>
{if $view.mcomments > 0}<p class="right">{$view.mcomments} {str tag=comments section=artefact.comment}</p>{/if}
</td>
<td>
<ul>
{foreach from=$view.comments key=commenter item=info}
{if $info.commenter|is_string}
<li>{$info.commenter}<span class="right">{$info.count}</span></li>
{elseif ! $info.member}
<li><a href="{$WWWROOT}user/view.php?id={$info.commenter}">{$info.commenter|display_name:null:true|escape}</a><span class="right">{$info.count}</span></li>
{/if}
{/foreach}
</ul>
{if $view.ecomments > 0}<p class="right">{$view.ecomments} {str tag=comments section=artefact.comment}</p>{/if}
</td>
</tr>
{/foreach}
{elseif $svcount > 0}
<tr class="{cycle values='r0,r1'}"><td colspan="4" class="message">{str tag=groupsharedviewsscrolled section=group}<td></tr>
{else}
<tr class="{cycle values='r0,r1'}"><td colspan="4" class="message">{str tag=noviewssharedwithgroupyet section=group}<td></tr>
{/if}
</tbody>
</table>
<br/><br/>
<table class="fullwidth groupviewsreport">
<thead>
<thead>
<tr>
<th class="sv {if $sort == title && $direction == asc}asc{elseif $sort == title}sorted{/if}">
<a href="{$baseurl}&sort=title{if $sort == title && $direction == asc}&direction=desc{/if}">{str tag=viewsownedbygroup section=view}</a>
</th>
<th class="mc {if $sort == mcomments && $direction == asc}asc{elseif $sort == mcomments}sorted{/if}">
<a href="{$baseurl}&sort=mcomments{if $sort == mcomments && $direction == asc}&direction=desc{/if}">{str tag=membercommenters section=group}</a>
</th>
<th class="ec {if $sort == ecomments && $direction == asc}asc{elseif $sort == ecomments}sorted{/if}">
<a href="{$baseurl}&sort=ecomment{if $sort == ecomments && $direction == asc}&direction=desc{/if}">{str tag=extcommenters section=group}</a>
</th>
</tr>
</thead>
<tbody>
{if $groupviews}
{foreach from=$groupviews item=view}
<tr class="{cycle values='r0,r1'}">
<td><a href="{$view.fullurl}">{$view.title}</a></td>
<td>
<ul>
{foreach from=$view.comments key=commenter item=info}
{if $info.member}<li><a href="{$WWWROOT}user/view.php?id={$info.commenter}">{$info.commenter|display_name:null:true|escape}</a><span class="right">{$info.count}</span></li>{/if}
{/foreach}
</ul>
{if $view.mcomments > 0}<p class="right">{$view.mcomments} {str tag=comments section=artefact.comment}</p>{/if}
</td>
<td>
<ul>
{foreach from=$view.comments key=commenter item=info}
{if $info.commenter|is_string}
<li>{$info.commenter}<span class="right">{$info.count}</span></li>
{elseif ! $info.member}
<li><a href="{$WWWROOT}user/view.php?id={$info.commenter}">{$info.commenter|display_name:null:true|escape}</a><span class="right">{$info.count}</span></li>
{/if}
{/foreach}
</ul>
{if $view.ecomments > 0}<p class="right">{$view.ecomments} {str tag=comments section=artefact.comment}</p>{/if}
</td>
</tr>
{/foreach}
{elseif $gvcount > 0}
<tr class="{cycle values='r0,r1'}"><td colspan="3" class="message">{str tag=groupcreatedviewsscrolled section=group}<td></tr>
{else}
<tr class="{cycle values='r0,r1'}"><td colspan="3" class="message">{str tag=grouphasntcreatedanyviewsyet section=group}<td></tr>
{/if}
</tbody>
</table>
{$pagination|safe}
{/if}
{include file="footer.tpl"}
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