Commit 7a7673c0 authored by Nathan Lewis's avatar Nathan Lewis
Browse files

Add activity stream block (Bug #1316324)



Change-Id: I49c15aed9e36da0ff4ea4e1fa4d110c112a25215
Signed-off-by: default avatarNathan Lewis <nathan.lewis@totaralms.com>
parent 6eae7784
......@@ -127,8 +127,10 @@ function edit_comment_submit(Pieform $form, $values) {
require_once('activity.php');
$data = (object) array(
'commentid' => $comment->get('id'),
'viewid' => $viewid,
'usr' => $comment->get('author'),
'objecttype' => ActivityType::OBJECTTYPE_VIEW,
'objectid' => $viewid,
'additionalid' => $comment->get('id'),
);
activity_occurred('feedback', $data, 'artefact', 'comment');
......
......@@ -105,3 +105,9 @@ To see %s online, follow this link:
$string['artefactdefaultpermissions'] = 'Default comment permission';
$string['artefactdefaultpermissionsdescription'] = 'The selected artefact types will have comments enabled on creation. Users can override these settings for individual artefacts.';
// Activity stream helper messages.
$string['activitystreamcommentartefactone'] = '%s left %d comment on %s artefact "%s": %s';
$string['activitystreamcommentartefactmany'] = '%s left %d comments on %s artefact "%s": %s';
$string['activitystreamcommentviewone'] = '%s left %d comment on %s page "%s": %s';
$string['activitystreamcommentviewmany'] = '%s left %d comments on %s page "%s": %s';
......@@ -61,6 +61,7 @@ class PluginArtefactComment extends PluginArtefact {
'admin' => 0,
'delay' => 0,
'allownonemethod' => 1,
'onlyapplyifwatched' => 0,
'defaultmethod' => 'email',
)
);
......@@ -1005,8 +1006,10 @@ function delete_comment_submit(Pieform $form, $values) {
if ($deletedby != 'owner' && $comment->get('owner') != $USER->get('id')) {
// Notify owner
$data = (object) array(
'commentid' => $comment->get('id'),
'viewid' => $view->get('id'),
'usr' => $comment->get('author'),
'objecttype' => ActivityType::OBJECTTYPE_VIEW,
'objectid' => $view->get('id'),
'additionalid' => $comment->get('id'),
);
activity_occurred('feedback', $data, 'artefact', 'comment');
}
......@@ -1188,10 +1191,17 @@ function add_feedback_form_submit(Pieform $form, $values) {
}
require_once('activity.php');
$data = (object) array(
'commentid' => $comment->get('id'),
'viewid' => $view->get('id')
);
$data->usr = $comment->get('author');
if ($artefact) {
$data->objecttype = ActivityType::OBJECTTYPE_ARTEFACT;
$data->objectid = $data->onartefact;
}
else {
$data->objecttype = ActivityType::OBJECTTYPE_VIEW;
$data->objectid = $data->onview;
}
$data->additionalid = $comment->get('id');
activity_occurred('feedback', $data, 'artefact', 'comment');
if (isset($moderatemsg)) {
......@@ -1229,21 +1239,19 @@ function add_feedback_form_cancel_submit(Pieform $form) {
));
}
class ActivityTypeArtefactCommentFeedback extends ActivityTypePlugin {
protected $viewid;
protected $commentid;
class ActivityTypeArtefactCommentFeedback extends ActivityTypePlugin implements ActivityStreamable {
/**
* @param array $data Parameters:
* - viewid (int)
* - commentid (int)
* - objecttype (ActivityType::OBJECTTYPE_VIEW or ActivityType::OBJECTTYPE_ARTEFACT)
* - objectid (view or artefact id int)
* - usr (user id int
* - additionalid (comment id int)
*/
public function __construct($data, $cron=false) {
parent::__construct($data, $cron);
$comment = new ArtefactTypeComment($this->commentid);
$comment = new ArtefactTypeComment($data->additionalid);
$this->overridemessagecontents = true;
if ($onartefact = $comment->get('onartefact')) { // feedback on artefact
......@@ -1254,7 +1262,7 @@ class ActivityTypeArtefactCommentFeedback extends ActivityTypePlugin {
$userid = $artefactinstance->get('owner');
}
if (empty($this->url)) {
$this->url = 'artefact/artefact.php?artefact=' . $onartefact . '&view=' . $this->viewid;
$this->url = 'artefact/artefact.php?artefact=' . $onartefact . '&view=' . $this->objectid;
}
}
else { // feedback on view.
......@@ -1267,6 +1275,7 @@ class ActivityTypeArtefactCommentFeedback extends ActivityTypePlugin {
$this->url = 'view/view.php?id=' . $onview;
}
}
if (empty($userid)) {
return;
}
......@@ -1331,6 +1340,10 @@ class ActivityTypeArtefactCommentFeedback extends ActivityTypePlugin {
);
}
public function get_required_parameters() {
return array('objecttype', 'objectid', 'usr', 'additionalid');
}
public function get_plugintype(){
return 'artefact';
}
......@@ -1339,7 +1352,66 @@ class ActivityTypeArtefactCommentFeedback extends ActivityTypePlugin {
return 'comment';
}
public function get_required_parameters() {
return array('commentid', 'viewid');
public static function get_activity_body($activity) {
$helperinfo = new stdClass();
$subactivity = $activity->subactivity[0];
$comment = new ArtefactTypeComment($subactivity->additionalid);
$helperinfo->activity = $activity;
$helperinfo->activitysection = 'artefact.comment';
$helperinfo->includesubactivitycounts = true;
$helperinfo->snippet = $comment->get('description');
$artefactid = $comment->get('onartefact');
$viewid = $comment->get('onview');
if ($artefactid) {
self::set_helperinfo_with_artefact($helperinfo, $artefactid);
}
else {
self::set_helperinfo_with_view($helperinfo, $viewid);
}
return ActivityStreamHelper::get_standard_activity_body($helperinfo);
}
/**
* Configure the abhelper for a given artefact.
*
* @param int $artefactid
*/
private static function set_helperinfo_with_artefact($helperinfo, $artefactid) {
$helperinfo->activityidentifier = 'activitystreamcommentartefact';
$artefact = get_record('artefact', 'id', $artefactid);
$artefactowner = reset(artefact_get_owner_info(array($artefactid)));
$helperinfo->ownername = $artefactowner->name;
$helperinfo->ownerurl = $artefactowner->url;
$owneruserid = $artefact->owner;
if ($owneruserid) {
$helperinfo->owneruserid = $owneruserid;
}
$helperinfo->objecttitle = $artefact->title;
$helperinfo->objecturl = null; // TODO Link to artefact in future patch.
}
/**
* Prepare the abhelper for a given view.
*
* @param int $viewid
*/
private static function set_helperinfo_with_view($helperinfo, $viewid) {
$helperinfo->activityidentifier = 'activitystreamcommentview';
$view = new View($viewid);
$owneruserid = $view->get('owner');
$groupid = $view->get('group');
if ($owneruserid) {
$helperinfo->owneruserid = $owneruserid;
}
else if ($groupid) {
$helperinfo->ownername = $view->formatted_owner();
$helperinfo->ownerurl = get_config('wwwroot') . 'group/view.php?id=' . $groupid;
}
$helperinfo->objecttitle = $view->get('title');
$helperinfo->objecturl = $view->get_url();
}
}
......@@ -155,6 +155,8 @@ $string['timeouterror'] = 'File upload failed: try uploading the file again.';
$string['title'] = 'Name';
$string['titlefieldisrequired'] = 'The name field is required.';
$string['Type'] = 'Type';
$string['typefile'] = 'File';
$string['typefolder'] = 'Folder';
$string['upload'] = 'Upload';
$string['uploadagreement'] = 'Upload agreement';
$string['uploadagreementdescription'] = 'Enable this option if you would like to force users to agree to the text below before they can upload a file to the site.';
......
<?php
/**
* Creative Commons License Block type for Mahara
*
* @package mahara
* @subpackage blocktype-activitystream
* @author Nathan Lewis <nathan.lewis@totaralms.com>
* @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.
*
*/
defined('INTERNAL') || die();
$string['activitystream'] = 'Activity stream';
$string['description'] = 'Show history of activities';
$string['noactivities'] = 'There are no activities to display in this stream. This activity stream will be filled with
relevant activities as they occur.';
$string['noactivitieshomestream'] = 'There are no activities to display in your home stream. You may need to change
some notifications to "Home stream" so they will be displayed here. <a href="%s">Edit your notification settings</a>.';
$string['title'] = 'Activity stream';
This diff is collapsed.
<?php
/**
* @package mahara
* @subpackage tests
* @author Nathan Lewis <nathan.lewis@totaralms.com>
* @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.
*/
require_once(get_config('docroot') . '/blocktype/activitystream/lib.php');
class ArtefactAccessTest extends MaharaUnitTest {
private $viewer;
private $other;
private $friend12;
private $friend21;
private $group;
private $institution;
private $conditionstotest;
private $conditionstotestknownfriends;
const OBJECT_ID_PUBLIC = 1001;
const OBJECT_ID_LOGGEDIN = 1002;
const OBJECT_ID_FRIEND12 = 1003;
const OBJECT_ID_FRIEND21 = 1004;
const OBJECT_ID_USR = 1005;
const OBJECT_ID_GROUP = 1006;
// const OBJECT_ID_MYGROUPS = 1007;
const OBJECT_ID_INSTITUTION = 1008;
private $objectids = array(
self::OBJECT_ID_PUBLIC,
self::OBJECT_ID_LOGGEDIN,
self::OBJECT_ID_FRIEND12,
self::OBJECT_ID_FRIEND21,
self::OBJECT_ID_USR,
self::OBJECT_ID_GROUP,
// self::OBJECT_ID_MYGROUPS,
self::OBJECT_ID_INSTITUTION
);
private $testcases = array(
array('public', null, array(self::OBJECT_ID_PUBLIC => 1)),
array('loggedin', null, array(self::OBJECT_ID_LOGGEDIN => 1)),
array('friend12', null, array(self::OBJECT_ID_FRIEND12 => 1)),
array('friend21', null, array(self::OBJECT_ID_FRIEND21 => 1)),
array('usr', null, array(self::OBJECT_ID_USR => 1)),
array('group', null, array(self::OBJECT_ID_GROUP => 1)),
// array('mygroups', null, array(self::OBJECT_ID_GROUP => 1)),
array('institution', null, array(self::OBJECT_ID_INSTITUTION => 1)),
array('public', true, array(self::OBJECT_ID_PUBLIC => 1)),
array('loggedin', true, array(self::OBJECT_ID_LOGGEDIN => 1)),
array('friends', true, array(self::OBJECT_ID_FRIEND12 => 1, self::OBJECT_ID_FRIEND21 => 1)),
array('usr', true, array(self::OBJECT_ID_USR => 1)),
array('group', true, array(self::OBJECT_ID_GROUP => 1)),
// array('mygroups', true, array(self::OBJECT_ID_MYGROUPS => 1)),
array('institution', true, array(self::OBJECT_ID_INSTITUTION => 1)),
);
/**
* Shared setUp method.
*/
public function setUp() {
parent::setUp();
$this->institution = $this->create_test_institution(array('name' => 'testinstitution'));
// Other user.
$this->other = $this->create_test_user((object)array(
'username' => 'other',
'email' => 'other@localhost',
'firstname' => 'other',
'lastname' => 'other',
));
// Friend12.
$this->friend12 = $this->create_test_user((object)array(
'username' => 'friend12',
'email' => 'friend12@localhost',
'firstname' => 'friend12',
'lastname' => 'friend12',
));
// Friend21.
$this->friend21 = $this->create_test_user((object)array(
'username' => 'friend21',
'email' => 'friend21@localhost',
'firstname' => 'friend21',
'lastname' => 'friend21',
));
// Viewer.
$this->viewer = $this->create_test_user((object)array(
'username' => 'viewer',
'email' => 'viewer@localhost',
'firstname' => 'viewer',
'lastname' => 'viewer',
), 'testinstitution');
// They are a member of a group.
$this->group = $this->create_test_group(array(
'name' => 'test',
'grouptype' => 'standard',
'members' => array($this->viewer => 'member')
));
// Create two friend records so that they can be tested individually.
execute_sql("INSERT INTO {usr_friend} (usr1, usr2, ctime) VALUES ({$this->viewer}, {$this->friend21}, NOW())");
execute_sql("INSERT INTO {usr_friend} (usr2, usr1, ctime) VALUES ({$this->viewer}, {$this->friend12}, NOW())");
// Public.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_PUBLIC . ", 'html', 0, {$this->other}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, accesstype, ctime)
VALUES (" . self::OBJECT_ID_PUBLIC . ", 'public', NOW())");
// Loggedin.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_LOGGEDIN . ", 'html', 0, {$this->other}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, accesstype, ctime)
VALUES (" . self::OBJECT_ID_LOGGEDIN . ", 'loggedin', NOW())");
// Friends12.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_FRIEND12 . ", 'html', 0, {$this->friend12}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, accesstype, ctime)
VALUES (" . self::OBJECT_ID_FRIEND12 . ", 'friends', NOW())");
// Friends21.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_FRIEND21 . ", 'html', 0, {$this->friend21}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, accesstype, ctime)
VALUES (" . self::OBJECT_ID_FRIEND21 . ", 'friends', NOW())");
// Usr.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_USR . ", 'html', 0, {$this->other}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, usr, ctime)
VALUES (" . self::OBJECT_ID_USR . ", {$this->viewer}, NOW())");
// Group.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_GROUP . ", 'html', 0, {$this->other}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, \"group\", ctime)
VALUES (" . self::OBJECT_ID_GROUP . ", {$this->group}, NOW())");
/*
// My groups.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_MYGROUPS . ", 'html', 0, {$this->other}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, accesstype, ctime)
VALUES (" . self::OBJECT_ID_MYGROUPS . ", 'mygroups', NOW())");
*/
// Institution.
execute_sql("INSERT INTO {artefact} (id, artefacttype, container, owner, title, ctime, mtime, atime, authorname)
VALUES (" . self::OBJECT_ID_INSTITUTION . ", 'html', 0, {$this->other}, 'artefactaccesstest', NOW(), NOW(), NOW(), '')");
execute_sql("INSERT INTO {artefact_access} (artefact, institution, ctime)
VALUES (" . self::OBJECT_ID_INSTITUTION . ", 'testinstitution', NOW())");
// Get the things that are going to be tested.
$this->conditionstotest = get_artefact_access_conditions($this->viewer);
$this->conditionstotestknownfriends = get_artefact_access_conditions($this->viewer, true);
}
/**
* Public, loggedin, friends, friend12, friend21, usr, group.
* Variables: Are known friends.
*/
public function testUntestedArtefactAccessConditions() {
foreach ($this->conditionstotest as $conditionkey => $condition) {
$found = false;
foreach ($this->testcases as $testcase) {
if ($testcase[0] == $conditionkey && empty($testcase[1])) {
$found = true;
}
}
$this->assertEquals(true, $found, "condition: " . $conditionkey . "\nsql: " . $condition['sql']);
}
foreach ($this->conditionstotestknownfriends as $condition) {
$found = false;
foreach ($this->testcases as $testcase) {
if ($testcase[0] == $conditionkey && $testcase[1] === true) {
$found = true;
}
}
$this->assertEquals(true, $found, "condition: " . $conditionkey . "\nsql: " . $condition['sql']);
}
}
/**
* Public, loggedin, friends, friend12, friend21, usr, group.
* Variables: Are known friends.
*/
public function testGetArtefactAccessConditions() {
$viewer = $this->viewer;
foreach ($this->testcases as $testcase) {
$conditionkey = $testcase[0];
$knownfriends = $testcase[1];
$expectedactivityids = $testcase[2];
if ($knownfriends) {
$condition = $this->conditionstotestknownfriends[$conditionkey];
}
else {
$condition = $this->conditionstotest[$conditionkey];
}
$params = array();
$sql = "SELECT artefact.id FROM {artefact} artefact " . $condition['sql'] .
" WHERE artefact.title = 'artefactaccesstest'";
foreach($condition['params'] as $accessconditionparam) {
$params[] = $accessconditionparam;
}
$results = get_records_sql_array($sql, $params);
$this->assertEquals(count($expectedactivityids), count($results),
"condition: " . $conditionkey ."\nsql: " . $sql . "\nparams: " . implode(", ", $params));
if (count($results) == count($expectedactivityids)) {
foreach ($results as $result) {
$this->assertNotEmpty($expectedactivityids[$result->id],
"condition: " . $conditionkey . "\nsql: " . $sql . "\nparams: " . implode(", ", $params));
}
}
}
}
public function tearDown() {
execute_sql("DELETE FROM {usr_friend} WHERE usr1 = ? AND usr2 = ?", array($this->viewer, $this->friend21));
execute_sql("DELETE FROM {usr_friend} WHERE usr2 = ? AND usr1 = ?", array($this->viewer, $this->friend12));
foreach ($this->objectids as $id) {
execute_sql("DELETE FROM {artefact_access} WHERE artefact = ?", array($id));
execute_sql("DELETE FROM {artefact} WHERE id = ?", array($id));
}
parent::tearDown();
}
}
<?php
/**
* @package mahara
* @subpackage tests
* @author Nathan Lewis <nathan.lewis@totaralms.com>
* @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.
*/
require_once(get_config('docroot') . '/blocktype/activitystream/lib.php');
class HomeStreamAdditionalConditionsTest extends MaharaUnitTest {
private $homestream;
private $nothomestream;
const ACTIVITY_ID_NEW_ARTEFACT_WATCHED_HOMESTREAM = 1001;
const ACTIVITY_ID_NEW_ARTEFACT_WATCHED_NOTHOMESTREAM = 1002;
const ACTIVITY_ID_NEW_ARTEFACT_UNWATCHED_HOMESTREAM = 1003;
const ACTIVITY_ID_NEW_ARTEFACT_UNWATCHED_NOTHOMESTREAM = 1004;
const ACTIVITY_ID_NEW_VIEW_WATCHED_HOMESTREAM = 1005;
const ACTIVITY_ID_NEW_VIEW_WATCHED_NOTHOMESTREAM = 1006;
const ACTIVITY_ID_NEW_VIEW_UNWATCHED_HOMESTREAM = 1007;
const ACTIVITY_ID_NEW_VIEW_UNWATCHED_NOTHOMESTREAM = 1008;
const ACTIVITY_ID_CHANGED_ARTEFACT_WATCHED_HOMESTREAM = 1009;
const ACTIVITY_ID_CHANGED_ARTEFACT_WATCHED_NOTHOMESTREAM = 1010;
const ACTIVITY_ID_CHANGED_ARTEFACT_UNWATCHED_HOMESTREAM = 1011;
const ACTIVITY_ID_CHANGED_ARTEFACT_UNWATCHED_NOTHOMESTREAM = 1012;
const ACTIVITY_ID_CHANGED_VIEW_WATCHED_HOMESTREAM = 1013;
const ACTIVITY_ID_CHANGED_VIEW_WATCHED_NOTHOMESTREAM = 1014;
const ACTIVITY_ID_CHANGED_VIEW_UNWATCHED_HOMESTREAM = 1015;
const ACTIVITY_ID_CHANGED_VIEW_UNWATCHED_NOTHOMESTREAM = 1016;
// Expect none that are NOTHOMESTREAM, none that are CHANGED UNWATCHED.
private $expectedids = array();
private $activityids = array();
private $artefactids = array();
private $viewids = array();
private $useractivityids = array('homestream' => array(), 'nothomestream' => array());
private $testnewaccess;
private $testchange;
/**
* Shared setUp method.
*/
public function setUp() {
parent::setUp();
// Homestreamuser.
$this->homestream = $this->create_test_user((object)array(
'username' => 'homestream',
'email' => 'homestream@localhost',
'firstname' => 'homestream',
'lastname' => 'homestream',
));
// Nothomestreamuser.
$this->nothomestream = $this->create_test_user((object)array(
'username' => 'nothomestream',
'email' => 'nothomestream@localhost',
'firstname' => 'nothomestream',
'lastname' => 'nothomestream',
));
$this->testnewaccess = insert_record('activity_type',
(object)array('name' => 'testnewaccess', 'defaultmethod' => 'homestream'));
$this->testchange = insert_record('activity_type',
(object)array('name' => 'testchange', 'defaultmethod' => 'homestream', 'onlyapplyifwatched' => 0));
$users = array('homestream', 'nothomestream');
$activitytypes = array($this->testnewaccess, $this->testchange);
$objecttypes = array('artefact', 'view');
$watchstatuses = array(true, false);
$id = 1000;
foreach ($activitytypes as $activitytype) {
foreach ($users as $user) {
foreach ($objecttypes as $objecttype) {
foreach ($watchstatuses as $watched) {
$id++;
$this->activityids[] = $id;
if ($objecttype == 'view') {
execute_sql("INSERT INTO {view} (id, type, owner, title, ctime, mtime, atime, numcolumns)
VALUES ({$id} + 1000, 'portfolio', {$this->$user}, '', NOW(), NOW(), NOW(), 0)");
$this->viewids[] = $id + 1000;
if ($watched) {
execute_sql("INSERT INTO {usr_watchlist_view} (usr, view, ctime)
VALUES ({$this->$user}, {$id} + 1000, NOW())");
}
execute_sql("INSERT INTO {activity} (id, usr, activitytype, activitysubtype, objecttype,
objectid, ctime) VALUES ({$id}, {$this->$user}, {$activitytype}, 0, " .
ActivityType::OBJECTTYPE_VIEW . ", {$id} + 1000, NOW())");
}
else {
execute_sql("INSERT INTO {artefact} (id, artefacttype, owner, title, ctime, mtime, atime, authorname)
VALUES ({$id} + 2000, 'html', {$this->$user}, '', NOW(), NOW(), NOW(), '')");
$this->artefactids[] = $id + 2000;
execute_sql("INSERT INTO {activity} (id, usr, activitytype, activitysubtype, objecttype,
objectid, ctime) VALUES ({$id}, {$this->$user}, {$activitytype}, 0, " .
ActivityType::OBJECTTYPE_ARTEFACT . ", {$id} + 2000, NOW())");
}
if ($user == 'homestream' && ($activitytype == $this->testnewaccess || $watched)) {
$this->expectedids[$id] = 1;
}
$this->useractivityids[$user][] = $id;
}
}
}