Commit 3c7da73e authored by Clare Lenihan's avatar Clare Lenihan Committed by Clare Lenihan

Merge branch 'groupforums' of git+ssh://git.catalyst.net.nz/var/git/mahara into groupforums

Conflicts:

	htdocs/interaction/forum/lib.php
parents 3cdb523a a8b6cdf7
......@@ -54,7 +54,7 @@ if ($markasread) {
// normal processing
$type = param_alpha('type', 'all');
$type = param_alphanum('type', 'all');
$limit = param_integer('limit', 10);
$offset = param_integer('offset', 0);
......@@ -62,23 +62,26 @@ $userid = $USER->get('id');
if ($type == 'all') {
$count = count_records('notification_internal_activity', 'usr', $userid);
$records = get_records_array('notification_internal_activity', 'usr', $userid,
'ctime DESC', '*', $offset, $limit);
$sql = 'SELECT a.*, at.name AS type,at.plugintype, at.pluginname FROM {notification_internal_activity} a
JOIN {activity_type} at ON a.type = at.id
WHERE a.usr = ? ORDER BY ctime DESC';
$records = get_records_sql_array($sql, array($userid), $offset, $limit);
} else if ($type == 'adminmessages' && $USER->get('admin')) {
$count = count_records_select('notification_internal_activity', 'usr = ? AND type IN (
SELECT name FROM {activity_type} WHERE admin = ?)',
SELECT id FROM {activity_type} WHERE admin = ?)',
array($userid, 1));
$records = get_records_select_array('notification_internal_activity', 'usr = ? AND type IN (
SELECT name FROM {activity_type} WHERE admin = ?)',
array($userid, 1),
'ctime DESC', '*', $offset, $limit);
$sql = 'SELECT a.*, at.name AS type,at.plugintype, at.pluginname FROM {notification_internal_activity} a
JOIN {activity_type} at ON a.type = at.id
WHERE a.usr = ? AND at.admin = ? ORDER BY ctime DESC';
$records = get_records_sql_array($sql, array($userid, 1), $offset, $limit);
}
else {
$count = count_records_select('notification_internal_activity', 'usr = ? AND type = ?',
array($userid,$type));
$records = get_records_select_array('notification_internal_activity', 'usr = ? AND type = ?',
array($userid, $type),
'ctime DESC', '*', $offset, $limit);
$sql = 'SELECT a.*, at.name AS type,at.plugintype, at.pluginname FROM {notification_internal_activity} a
JOIN {activity_type} at ON a.type = at.id
WHERE a.usr = ? AND a.type = ?';
$records = get_records_sql_array($sql, array($userid, $type), $offset, $limit);
}
if (empty($records)) {
......@@ -90,7 +93,11 @@ $unread = get_string('unread', 'activity');
foreach ($records as &$r) {
$r->date = format_date(strtotime($r->ctime));
$r->type = get_string('type' . $r->type, 'activity');
$section = 'activity';
if (!empty($r->plugintype)) {
$section = $r->plugintype . '.' . $r->pluginname;
}
$r->type = get_string('type' . $r->type, $section);
$r->message = format_whitespace($r->message);
}
......
......@@ -32,10 +32,18 @@ define('SECTION_PAGE', 'activity');
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
$types = get_records_array('activity_type', 'admin', 0);
$types = get_records_assoc('activity_type', 'admin', 0, 'plugintype,pluginname,name', 'id,name,plugintype,pluginname');
$types = array_map(create_function('$a', '
if (!empty($a->plugintype)) {
$section = "{$a->plugintype}.{$a->pluginname}";
}
else {
$section = "activity";
}
return get_string("type" . $a->name, $section);
'), $types);
if ($USER->get('admin')) {
$admintypes = get_records_array('activity_type');
$types[] = (object)array('name' => 'adminmessages');
$types['adminmessages'] = get_string('typeadminmessages', 'activity');
}
$morestr = get_string('more...');
......
......@@ -56,18 +56,24 @@ foreach ($activitytypes as $type) {
$dv = 'internal';
}
}
$elements[$type->name] = array(
if (!empty($type->plugintype)) {
$section = $type->plugintype . '.' . $type->pluginname;
}
else {
$section = 'activity';
}
$elements[$type->id] = array(
'defaultvalue' => $dv,
'type' => 'select',
'title' => get_string('type' . $type->name, 'activity'),
'title' => get_string('type' . $type->name, $section),
'options' => $options,
'rules' => array(
'required' => true
)
);
if (!empty($type->admin)) {
$elements[$type->name]['rules']['required'] = false;
$elements[$type->name]['options']['none'] = get_string('none');
$elements[$type->id]['rules']['required'] = false;
$elements[$type->id]['options']['none'] = get_string('none');
}
}
......@@ -98,11 +104,11 @@ function activityprefs_submit(Pieform $form, $values) {
$userid = $USER->get('id');
foreach ($activitytypes as $type) {
if ($values[$type->name] == 'none') {
$USER->set_activity_preference($type->name, null);
if ($values[$type->id] == 'none') {
$USER->set_activity_preference($type->id, null);
}
else {
$USER->set_activity_preference($type->name, $values[$type->name]);
$USER->set_activity_preference($type->id, $values[$type->id]);
}
}
$form->json_reply(PIEFORM_OK, get_string('prefssaved', 'account'));
......
......@@ -73,7 +73,7 @@ function adminusers_submit(Pieform $form, $values) {
SET admin = 1
WHERE id IN (' . join(',', $values['users']) . ')');
execute_sql('DELETE FROM {usr_activity_preference}
WHERE activity IN (SELECT name FROM {activity_type}
WHERE activity IN (SELECT id FROM {activity_type}
WHERE admin = 1)
AND usr NOT IN (' . join(',', $values['users']) . ')');
db_commit();
......
......@@ -35,16 +35,22 @@ define('SECTION_PAGE', 'notifications');
require_once('pieforms/pieform.php');
$sql = 'SELECT u.*, a.activity, a.method
$sql = 'SELECT u.*, a.activity, a.method
FROM {usr} u
LEFT JOIN {usr_activity_preference} a ON a.usr = u.id
WHERE u.admin = ?';
$admins = get_records_sql_array($sql, array(1));
$types = get_column('activity_type', 'name', 'admin', 1);
$types = array_flip($types);
foreach (array_keys($types) as $k) {
$types[$k] = get_string('type' . $k, 'activity');
$temptypes = get_records_array('activity_type', 'admin', 1);
$types = array();
foreach ($temptypes as $t) {
if (empty($t->plugintype)) {
$section = 'activity';
}
else {
$section = $t->plugintype . '.' . $t->pluginname;
}
$types[$t->id] = get_string('type' . $t->name, $section);
}
$users = array();
foreach ($admins as $u) {
......
......@@ -256,7 +256,7 @@ class User {
* This function returns a method for a particular
* activity type, or null if it's not set.
*
* @param string $key the activity type
* @param int $key the activity type id
*/
public function get_activity_preference($key) {
$activityprefs = $this->get('activityprefs');
......
......@@ -48,8 +48,8 @@ if ($postid==0) {
}
if (isset($postid)) {
$info = get_record_sql(
'SELECT p.topic, p.poster, p.ctime, t.forum, f.group
$post = get_record_sql(
'SELECT p.subject, p.body, p.parent, p.topic, p.poster, p.ctime, t.forum, f.group
FROM {interaction_forum_post} p
INNER JOIN {interaction_forum_topic} t
ON (p.topic = t.id)
......@@ -58,27 +58,19 @@ if (isset($postid)) {
WHERE p.id = ?',
array($postid)
);
$topicid = $info->topic;
$topicid = $post->topic;
$membership = user_can_access_group((int)$info->group);
$membership = user_can_access_group((int)$post->group);
$admin = (bool)($membership & GROUP_MEMBERSHIP_OWNER);
$moderator = $admin || is_forum_moderator((int)$info->forum);
$moderator = $admin || is_forum_moderator((int)$post->forum);
if (!$moderator &&
($info->poster != $userid
|| (time() - strtotime($info->ctime)) > (30 * 60))) {
($post->poster != $userid
|| (time() - strtotime($post->ctime)) > (30 * 60))) {
throw new AccessDeniedException();
}
$postinfo = get_record_sql(
'SELECT p.subject, p.body, p.topic
FROM {interaction_forum_post} p
WHERE id = ?',
array($postid)
);
$topicid = $postinfo->topic;
}
require_once('pieforms/pieform.php');
......@@ -90,9 +82,10 @@ $editform = pieform(array(
'subject' => array(
'type' => 'text',
'title' => get_string('subject', 'interaction.forum'),
'defaultvalue' => isset($postinfo) ? $postinfo->subject : null,
'defaultvalue' => isset($post) ? $post->subject : null,
'rules' => array(
'maxlength' => 255
'maxlength' => 255,
'required' => isset($post) && !$post->parent ? true : false
)
),
'body' => array(
......@@ -100,13 +93,13 @@ $editform = pieform(array(
'title' => get_string('body', 'interaction.forum'),
'rows' => 10,
'cols' => 70,
'defaultvalue' => isset($postinfo) ? $postinfo->body : null,
'defaultvalue' => isset($post) ? $post->body : null,
'rules' => array( 'required' => true )
),
'submit' => array(
'type' => 'submitcancel',
'value' => array(
isset($postinfo) ? get_string('edit', 'interaction.forum') : get_string('post','interaction.forum'),
isset($post) ? get_string('edit', 'interaction.forum') : get_string('post','interaction.forum'),
get_string('cancel', 'interaction.forum')
),
'goto' => get_config('wwwroot') . 'interaction/forum/topic.php?id='.$topicid
......@@ -154,7 +147,7 @@ function editpost_submit(Pieform $form, $values) {
array('id' => $postid)
);
if ($topic->poster != $USER->get('id') ||
(time() - strtotime($topic->posttime)) > (30 * 60)) {
(time() - strtotime($topic->posttime)) > (30 * 60)) {
insert_record(
'interaction_forum_edit',
(object)array(
......
......@@ -32,6 +32,7 @@ $string['stickytopics'] = 'Sticky topics';
$string['subject'] = 'Subject';
$string['subscribe'] = 'Subscribe';
$string['topic'] = 'Topic';
$string['unsubscribe'] = 'Unsubscribe';6
$string['typenewpost'] = 'New post';
$string['unsubscribe'] = 'Unsubscribe';
?>
......@@ -3,7 +3,19 @@
class PluginInteractionForum extends PluginInteraction {
public static function instance_config_form($instance=null) {
return array();
return array(
);
}
public static function get_activity_types() {
return array(
(object)array(
'name' => 'newpost',
'admin' => 0,
'delay' => 1,
)
);
}
}
......@@ -15,6 +27,13 @@ class InteractionForumInstance extends InteractionInstance {
}
class ActivityTypeInteractionForumNewPost extends ActivityType {
public function get_required_parameters() {
return array();
}
}
/**
* Is a user a moderator of a given forum
*
......@@ -34,8 +53,8 @@ function is_forum_moderator($forumid, $userid=null) {
if (!is_int($forumid)) {
throw new InvalidArgumentException("non integer forum id given to is_forum_moderator: $forumid");
}
return record_exists_sql(
'SELECT "user"
FROM {interaction_forum_moderator}
......
......@@ -3,7 +3,7 @@
{include file="columnleftstart.tpl"}
<h3>{$heading|escape}</h3>
<h2>{$heading|escape}</h2>
{$deleteform}
{include file="columnleftend.tpl"}
......
......@@ -3,7 +3,7 @@
{include file="columnleftstart.tpl"}
<h3>{$heading|escape}</h3>
<h2>{$heading|escape}</h2>
{$deleteform}
{include file="columnleftend.tpl"}
......
......@@ -2,6 +2,8 @@
{include file="sidebar.tpl"}
{include file="columnleftstart.tpl"}
<h2>{str tag=nameplural section=interaction.forum}</h2>
{if $admin}
<a href="{$WWWROOT}interaction/edit.php?group={$group|escape}&plugin=forum">{str tag="newforum" section=interaction.forum}</a>
{/if}
......
......@@ -3,7 +3,7 @@
{include file="columnleftstart.tpl"}
<h3>{$subject}</h3>
<h2>{$subject}</h2>
<ul>
<li>
{$posts}
......
......@@ -2,7 +2,7 @@
{include file="sidebar.tpl"}
{include file="columnleftstart.tpl"}
<h3>{$forum->title|escape}</h3>
<h2>{$forum->title|escape}</h2>
<p>{$forum->description}</p>
<a href="{$WWWROOT}interaction/forum/edittopic.php?forum={$forum->id|escape}">{str tag="newtopic" section="interaction.forum}</a>
<br>
......
<?php
$config->version = 2007111300;
$config->version = 2007111303;
$config->release = '0.1';
?>
......@@ -33,14 +33,11 @@ defined('INTERNAL') || die();
* @param string $activitytype type of activity
* @param mixed $data data
*/
function activity_occurred($activitytype, $data) {
if (!$at = get_record('activity_type', 'name', $activitytype)) {
throw new Exception("Invalid activity type $activitytype");
}
function activity_occurred($activitytype, $data, $plugintype=null, $pluginname=null) {
$at = activity_locate_typerecord($activitytype, $plugintype, $pluginname);
if (!empty($at->delay)) {
$delayed = new StdClass;
$delayed->type = $activitytype;
$delayed->type = $at->id;
$delayed->data = serialize($data);
$delayed->ctime = db_format_timestamp(time());
insert_record('activity_queue', $delayed);
......@@ -74,21 +71,9 @@ function activity_occurred($activitytype, $data) {
*/
function handle_activity($activitytype, $data, $cron=false) {
// mysql compatibility (sigh...)
$casturl = 'CAST(? AS TEXT)';
if (get_config('dbtype') == 'mysql') {
$casturl = 'CAST(? AS CHAR)'; // note, NOT varchar
}
$data = (object)$data;
if (is_string($activitytype)) {
$activitytype = get_record('activity_type', 'name', $activitytype);
}
if (!is_object($activitytype)) {
throw new InvalidArgumentException("Invalid activitytype $activitytype");
}
$activitytype = activity_locate_typerecord($activitytype);
$classname = 'ActivityType' . ucfirst($activitytype->name);
if (!empty($activitytype->plugintype)) {
......@@ -106,7 +91,7 @@ function handle_activity($activitytype, $data, $cron=false) {
$data = $activity->to_stdclass();
safe_require('notification', 'internal', 'lib.php', 'require_once');
$data->type = $activity->get_type();
$data->type = $activity->get_id();
foreach ($activity->get_users() as $user) {
$userdata = $data;
// some stuff gets overridden by user specific stuff
......@@ -144,7 +129,7 @@ function handle_activity($activitytype, $data, $cron=false) {
* for a particular activitytype
* including the notification method.
*
* @param string $activitytype the name of the activity type
* @param int $activitytype the id of the activity type
* @param array $userids an array of userids to filter by
* @param array $userobjs an array of user objects to filterby
* @param bool $adminonly whether to filter by admin flag
......@@ -201,7 +186,7 @@ function activity_process_queue() {
}
function activity_get_viewaccess_users($view, $owner, $type) {
$type = activity_locate_typerecord($type);
$sql = 'SELECT userid, u.*, p.method
FROM (
SELECT (CASE WHEN usr1 = ? THEN usr2 ELSE usr1 END) AS userid
......@@ -224,13 +209,35 @@ function activity_get_viewaccess_users($view, $owner, $type) {
JOIN {usr} u ON u.id = userlist.userid
LEFT JOIN {usr_activity_preference} p ON p.usr = u.id
WHERE p.activity = ?';
$values = array($owner, $owner, $owner, 'friends', $view, $view, $view, 0, 1, $view, $type);
$values = array($owner, $owner, $owner, 'friends', $view, $view, $view, 0, 1, $view, $type->id);
if (!$u = get_records_sql_assoc($sql, $values)) {
$u = array();
}
return $u;
}
function activity_locate_typerecord($activitytype, $plugintype=null, $pluginname=null) {
if (is_object($activitytype)) {
return $activitytype;
}
if (is_numeric($activitytype)) {
$at = get_record('activity_type', 'id', $activitytype);
}
else {
if (empty($plugintype) && empty($pluginname)) {
$at = get_record_select('activity_type',
'name = ? AND plugintype IS NULL AND pluginname IS NULL',
array($activitytype));
}
else {
$at = get_record('activity_type', 'name', $activitytype, 'plugintype', $plugintype, 'pluginname', $pluginname);
}
}
if (empty($at)) {
throw new Exception("Invalid activity type $activitytype");
}
return $at;
}
/** activity type classes **/
abstract class ActivityType {
......@@ -239,6 +246,15 @@ abstract class ActivityType {
protected $message;
protected $users = array();
protected $url;
protected $id;
public function get_id() {
if (!isset($this->id)) {
$tmp = activity_locate_typerecord($this->get_type());
$this->id = $tmp->id;
}
return $this->id;
}
public function get_type() {
$prefix = 'ActivityType';
......@@ -287,8 +303,7 @@ abstract class ActivityTypeAdmin extends ActivityType {
public function __construct($data) {
parent::__construct($data);
$this->users = activity_get_users($this->get_type(), null, null, true);
log_debug($this->users);
$this->users = activity_get_users($this->get_id(), null, null, true);
}
}
......@@ -378,7 +393,7 @@ class ActivityTypeMaharamessage extends ActivityType {
public function __construct($data) {
parent::__construct($data);
$this->users = activity_get_users('maharamessage', $this->users);
$this->users = activity_get_users($this->get_id(), $this->users);
}
public function get_required_parameters() {
......@@ -396,7 +411,7 @@ class ActivityTypeUsermessage extends ActivityType {
if (empty($this->subject)) {
$this->subject = get_string('newusermessage', 'mahara', display_name($this->userfrom));
}
$this->users = activity_get_users('usermessage', array($this->userto));
$this->users = activity_get_users($this->get_id(), array($this->userto));
if (empty($this->url)) {
$this->url = get_config('wwwroot') . 'user/view.php?id=' . $this->userfrom;
}
......@@ -442,7 +457,7 @@ class ActivityTypeFeedback extends ActivityType {
}
}
if ($userid) {
$this->users = activity_get_users('feedback', array($userid));
$this->users = activity_get_users($this->get_id(), array($userid));
}
}
......@@ -468,6 +483,11 @@ class ActivityTypeWatchlist extends ActivityType {
throw new ViewNotFoundException(get_string('viewnotfound', 'error', $this->view));
}
$this->message = $oldsubject . ' ' . $viewinfo->title;
// mysql compatibility (sigh...)
$casturl = 'CAST(? AS TEXT)';
if (get_config('dbtype') == 'mysql') {
$casturl = 'CAST(? AS CHAR)'; // note, NOT varchar
}
$sql = 'SELECT u.*, p.method, ' . $casturl . ' AS url
FROM {usr_watchlist_view} wv
JOIN {usr} u
......@@ -511,7 +531,7 @@ class ActivityTypeNewview extends ActivityType {
$this->url = get_config('wwwroot') . 'view/view.php?id=' . $this->view;
// add users on friendslist or userlist...
$this->users = activity_get_viewaccess_users($this->view, $this->owner, 'newview');
$this->users = activity_get_viewaccess_users($this->view, $this->owner, $this->get_id());
// ick
foreach ($this->users as &$user) {
$user->message = display_name($viewinfo, $user) . ' ' . $this->message;
......@@ -544,7 +564,7 @@ class ActivityTypeViewaccess extends ActivityType {
$this->subject = get_string('newviewaccesssubject', 'activity');
$this->url = get_config('wwwroot') . 'view/view.php?id=' . $this->view;
$this->users = array_diff_key(
activity_get_viewaccess_users($this->view, $this->owner, 'viewaccess'),
activity_get_viewaccess_users($this->view, $this->owner, $this->get_id()),
$this->oldusers
);
......@@ -559,4 +579,19 @@ class ActivityTypeViewaccess extends ActivityType {
}
}
abstract class ActivityTypePlugin extends ActivityType {
abstract public function get_plugintype();
abstract public function get_pluginname();
public function get_id() {
if (!isset($this->id)) {
$tmp = activity_locate_typerecord($this->get_type(), $this->get_plugintype(), $this->get_pluginname());
$this->id = $tmp->id;
}
return $this->id;
}
}
?>
......@@ -155,24 +155,28 @@
</TABLE>
<TABLE NAME="activity_type">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" />
<FIELD NAME="name" TYPE="char" LENGTH="50" NOTNULL="true" />
<FIELD NAME="admin" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" />
<FIELD NAME="delay" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" />
<FIELD NAME="plugintype" TYPE="char" LENGTH="25" NOTNULL="false" />
<FIELD NAME="pluginname" TYPE="char" LENGTH="255" NOTNULL="false" />
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="name" />
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
<KEY NAME="namepluginuk" TYPE="unique" FIELDS="name, plugintype, pluginname" />
</KEYS>
</TABLE>
<TABLE NAME="activity_queue">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" />
<FIELD NAME="type" TYPE="char" LENGTH="50" NOTNULL="true" />
<FIELD NAME="type" TYPE="int" LENGTH="10" NOTNULL="true" />
<FIELD NAME="data" TYPE="text" NOTNULL="true" />
<FIELD NAME="ctime" TYPE="datetime" />
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
<KEY NAME="typefk" TYPE="foreign" FIELDS="type" REFTABLE="activity_type" REFFIELDS="name" />
<KEY NAME="typefk" TYPE="foreign" FIELDS="type" REFTABLE="activity_type"