Commit 32c23e45 authored by Robert Lyon's avatar Robert Lyon

Bug 1472467: Adding journals to institution level

This patch should do the following:
Add a new site / institution menu item called 'Journals'
Allow an institution to add Journals
An admin can add entries to the journal
A newly created user can get a copy of the journal

Change-Id: I1fc424824fefe548d253e4c55d234ac3456484a8
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent 98ba05cc
......@@ -97,6 +97,12 @@ class PluginBlocktypeBlog extends PluginBlocktype {
else {
$smarty->assign('artefacttitle', hsc($blog->get('title')));
}
// Only show the 'New entry' link for blogs that you can add an entry to
$canaddpost = false;
$institution = $blog->get('institution');
if (ArtefactTypeBlog::can_edit_blog($blog, $institution)) {
$canaddpost = true;
}
$smarty->assign('options', $configdata);
$smarty->assign('description', $blog->get('description'));
......@@ -104,6 +110,7 @@ class PluginBlocktypeBlog extends PluginBlocktype {
$smarty->assign('tags', $blog->get('tags'));
$smarty->assign('blockid', $instance->get('id'));
$smarty->assign('editing', $editing);
$smarty->assign('canaddpost', $canaddpost);
$smarty->assign('blogid', $blog->get('id'));
$smarty->assign('posts', $posts);
......@@ -122,6 +129,10 @@ class PluginBlocktypeBlog extends PluginBlocktype {
safe_require('artefact', 'blog');
$configdata = $instance->get('configdata');
require_once(get_config('libroot') . 'view.php');
$view = new View($instance->get('view'));
$institution = $view->get('institution');
if (!empty($configdata['artefactid'])) {
$blog = $instance->get_artefact_instance($configdata['artefactid']);
}
......@@ -136,8 +147,21 @@ class PluginBlocktypeBlog extends PluginBlocktype {
//
// Note: the owner check will have to change when we do group/site
// blogs
if (empty($configdata['artefactid']) || $blog->get('owner') == $USER->get('id')) {
$elements[] = self::artefactchooser_element((isset($configdata['artefactid'])) ? $configdata['artefactid'] : null);
if (empty($configdata['artefactid'])
|| (ArtefactTypeBlog::can_edit_blog($blog, $institution))) {
$where = array('blog');
$sql = "SELECT a.id FROM {artefact} a
WHERE a.artefacttype = ?";
if ($institution) {
$sql .= " AND a.institution = ?";
$where[] = $institution;
}
else {
$sql .= " AND a.owner = ?";
$where[] = $USER->get('id');
}
$blogids = get_column_sql($sql, $where);
$elements[] = self::artefactchooser_element((isset($configdata['artefactid'])) ? $configdata['artefactid'] : null, $blogids);
$elements['count'] = array(
'type' => 'text',
'title' => get_string('postsperpage', 'blocktype.blog/blog'),
......@@ -195,7 +219,7 @@ class PluginBlocktypeBlog extends PluginBlocktype {
return $artefacts;
}
public static function artefactchooser_element($default=null) {
public static function artefactchooser_element($default=null, $blogids=array()) {
return array(
'name' => 'artefactid',
'type' => 'artefactchooser',
......@@ -206,6 +230,7 @@ class PluginBlocktypeBlog extends PluginBlocktype {
'selectone' => true,
'artefacttypes' => array('blog'),
'template' => 'artefact:blog:artefactchooser-element.tpl',
'extraselect' => !empty($blogids) ? array(array('fieldname' => 'id', 'type' => 'int', 'values' => $blogids)) : null,
);
}
......@@ -214,11 +239,11 @@ class PluginBlocktypeBlog extends PluginBlocktype {
}
/**
* Blog blocktype is only allowed in personal views, because currently
* there's no such thing as group/site blogs
* Blog blocktype is only allowed in personal or institution views, because currently
* there's no such thing as group blogs
*/
public static function allowed_in_view(View $view) {
return $view->get('owner') != null;
return ($view->get('owner') != null || $view->get('institution') != null);
}
public static function feed_url(BlockInstance $instance) {
......
......@@ -118,14 +118,21 @@ class PluginBlocktypeBlogpost extends PluginBlocktype {
// choose a blog post to put in this block, when the one that is
// currently in it isn't choosable.
//
// Note: the owner check will have to change when we do group/site
// blogs
if (empty($configdata['artefactid']) || $blog->get('owner') == $USER->get('id')) {
$publishedposts = get_column_sql('
SELECT a.id
FROM {artefact} a
// Note: the owner check will have to change when we do group blogs
$institution = $instance->get('view_obj')->get('institution');
if (empty($configdata['artefactid']) || ArtefactTypeBlog::can_edit_blog($blog, $institution)) {
$sql = "SELECT a.id FROM {artefact} a
INNER JOIN {artefact_blog_blogpost} p ON p.blogpost = a.id
WHERE p.published = 1 AND a.owner= ?', array($USER->get('id')));
WHERE p.published = 1";
if ($institution) {
$sql .= " AND a.institution = ?";
$where = array($institution);
}
else {
$sql .= " AND a.owner = ?";
$where = array($USER->get('id'));
}
$publishedposts = get_column_sql($sql, $where);
$elements[] = self::artefactchooser_element((isset($configdata['artefactid'])) ? $configdata['artefactid'] : null, $publishedposts);
$elements[] = PluginArtefactBlog::block_advanced_options_element($configdata, 'blogpost');
}
......@@ -187,11 +194,11 @@ class PluginBlocktypeBlogpost extends PluginBlocktype {
}
/**
* Blogpost blocktype is only allowed in personal views, because currently
* there's no such thing as group/site blogs
* Blogpost blocktype is only allowed in personal and institution views, because currently
* there's no such thing as group blogs
*/
public static function allowed_in_view(View $view) {
return $view->get('owner') != null;
return ($view->get('owner') != null || $view->get('institution') != null);
}
}
......@@ -10,7 +10,6 @@
*/
define('INTERNAL', 1);
define('MENUITEM', 'content/blogs');
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'blog');
define('SECTION_PAGE', 'index');
......@@ -18,10 +17,6 @@ define('SECTION_PAGE', 'index');
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
safe_require('artefact', 'blog');
if (!$USER->get_account_preference('multipleblogs')) {
redirect(get_config('wwwroot') . 'artefact/blog/view/index.php');
}
define('TITLE', get_string('blogs','artefact.blog'));
if ($delete = param_integer('delete', 0)) {
......@@ -31,16 +26,62 @@ if ($delete = param_integer('delete', 0)) {
$blogs = (object) array(
'offset' => param_integer('offset', 0),
'limit' => param_integer('limit', 10),
'institution' => null,
'data' => false,
'pagination_js' => false,
);
list($blogs->count, $blogs->data) = ArtefactTypeBlog::get_blog_list($blogs->limit, $blogs->offset);
$institutionname = null;
if ($institution = param_alphanum('institution', null)) {
if ($institution == 'mahara') {
$institutionname = $institution;
if (!($USER->get('admin'))) {
throw new AccessDeniedException();
}
$institutiontitle = get_string('siteblogs', 'artefact.blog');
}
else {
$s = institution_selector_for_page($institution, get_config('wwwroot') . 'artefact/blog/index.php');
$institutionname = $s['institution'];
if (!($USER->get('admin') || $USER->is_institutional_admin())) {
throw new AccessDeniedException();
}
$institutiontitle = get_string('institutionblogs', 'artefact.blog');
}
$blogs->institution = $institutionname;
}
PluginArtefactBlog::set_blog_nav($institution, $institutionname);
list($blogs->count, $blogs->data) = ArtefactTypeBlog::get_blog_list($blogs->limit, $blogs->offset, $blogs->institution);
if (!empty($blogs->institution)) {
require_once(get_config('libroot') . 'institution.php');
$institution = new Institution($blogs->institution);
}
else {
if (!$USER->get_account_preference('multipleblogs')) {
$extra = !empty($institution) ? '?institution=' . $institution : '';
redirect(get_config('wwwroot') . 'artefact/blog/view/index.php' . $extra);
}
}
ArtefactTypeBlog::build_blog_list_html($blogs);
$smarty = smarty(array('paginator'));
$smarty->assign_by_ref('blogs', $blogs);
$smarty->assign('institutionname', $institutionname);
$smarty->assign('PAGEHEADING', TITLE);
$smarty->assign('INLINEJAVASCRIPT', 'addLoadEvent(function() {' . $blogs->pagination_js . '});');
$js = '';
if ($blogs->pagination_js) {
$js .= 'addLoadEvent(function() {' . $blogs->pagination_js . '});';
}
if (!empty($institutionname) && ($institutionname != 'mahara')) {
$smarty->assign('institution', $institutionname);
$smarty->assign('institutionselector', $s['institutionselector']);
$js .= $s['institutionselectorjs'];
}
$smarty->assign('INLINEJAVASCRIPT', $js);
$smarty->display('artefact:blog:index.tpl');
function delete_blog_submit(Pieform $form, $values) {
......@@ -48,6 +89,7 @@ function delete_blog_submit(Pieform $form, $values) {
require_once('embeddedimage.php');
$blog = new ArtefactTypeBlog($values['delete']);
$blog->check_permission();
$institution = $blog->get('institution');
if ($blog->get('locked')) {
$SESSION->add_error_msg(get_string('submittedforassessment', 'view'));
}
......@@ -56,5 +98,8 @@ function delete_blog_submit(Pieform $form, $values) {
EmbeddedImage::delete_embedded_images('blog', $blog->get('id'));
$SESSION->add_ok_msg(get_string('blogdeleted', 'artefact.blog'));
}
if ($institution) {
redirect('/artefact/blog/index.php?institution=' . $institution);
}
redirect('/artefact/blog/index.php');
}
......@@ -15,6 +15,8 @@ $string['pluginname'] = 'Journals';
$string['blog'] = 'Journal';
$string['blogs'] = 'Journals';
$string['siteblogs'] = 'Site journals';
$string['institutionblogs'] = 'Institution journals';
$string['addblog'] = 'Create journal';
$string['addpost'] = 'New entry';
$string['alignment'] = 'Alignment';
......@@ -73,6 +75,8 @@ $string['mustspecifycontent'] = 'You must specify some content for your entry';
$string['name'] = 'Name';
$string['newattachmentsexceedquota'] = 'The total size of the new files that you have uploaded to this entry would exceed your quota. You may be able to save the entry if you remove some of the attachments you have just added.';
$string['newblog'] = 'New journal';
$string['newblogsite'] = 'New site journal';
$string['newbloginstitution'] = 'New "%s" journal';
$string['newblogpost'] = 'New journal entry in journal "%s"';
$string['newerposts'] = 'Newer entries';
$string['nodefaultblogfound'] = 'No default journal found. This is a bug in the system. To fix it, you need to enable the multiple journals option on the <a href="%saccount/index.php">account settings</a> page.';
......@@ -114,6 +118,7 @@ $string['verticalspace'] = 'Vertical space';
$string['viewblog'] = 'View journal';
$string['youarenottheownerofthisblog'] = 'You are not the owner of this journal.';
$string['youarenottheownerofthisblogpost'] = 'You are not the owner of this journal entry.';
$string['youarenotanadminof'] = 'You are not an admin of the "%s" institution.';
$string['cannotdeleteblogpost'] = 'An error occurred removing this journal entry.';
$string['baseline'] = 'Baseline';
......
......@@ -31,6 +31,44 @@ class PluginArtefactBlog extends PluginArtefact {
return 'blog';
}
public static function admin_menu_items() {
$map['manageinstitutions/blogs'] = array(
'path' => 'manageinstitutions/blogs',
'url' => 'artefact/blog/index.php?institution=1',
'title' => get_string('blogs', 'artefact.blog'),
'weight' => 75,
);
$map['configsite/blogs'] = array(
'path' => 'configsite/blogs',
'url' => 'artefact/blog/index.php?institution=mahara',
'title' => get_string('blogs', 'artefact.blog'),
'weight' => 65,
);
if (defined('MENUITEM') && isset($map[MENUITEM])) {
$map[MENUITEM]['selected'] = true;
}
return $map;
}
public static function institution_menu_items() {
return self::admin_menu_items();
}
public static function set_blog_nav($institution = false, $institutionname = null) {
if ($institutionname == 'mahara') {
define('ADMIN', 1);
define('MENUITEM', 'configsite/blogs');
}
else if ($institution) {
define('INSTITUTIONALADMIN', 1);
define('MENUITEM', 'manageinstitutions/blogs');
}
else {
define('MENUITEM', 'content/blogs');
}
}
public static function is_active() {
return get_field('artefact_installed', 'active', 'name', 'blog');
}
......@@ -40,15 +78,9 @@ class PluginArtefactBlog extends PluginArtefact {
$tab = array(
'path' => 'content/blogs',
'weight' => 40,
'url' => 'artefact/blog/index.php',
'title' => get_string('blogs', 'artefact.blog'),
);
if ($USER->get_account_preference('multipleblogs')) {
$tab['url'] = 'artefact/blog/index.php';
$tab['title'] = get_string('blogs', 'artefact.blog');
}
else {
$tab['url'] = 'artefact/blog/view/index.php';
$tab['title'] = get_string('blog', 'artefact.blog');
}
return array('content/blogs' => $tab);
}
......@@ -182,8 +214,18 @@ class ArtefactTypeBlog extends ArtefactType {
*/
public function check_permission() {
global $USER;
if ($USER->get('id') != $this->owner) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblog', 'artefact.blog'));
if (!empty($this->institution)) {
if ($this->institution == 'mahara' && !$USER->get('admin')) {
throw new AccessDeniedException(get_string('youarenotasiteadmin', 'artefact.blog'));
}
else if (!$USER->get('admin') && !$USER->is_institutional_admin($this->institution)) {
throw new AccessDeniedException(get_string('youarenotanadminof', 'artefact.blog', $this->institution));
}
}
else {
if ($USER->get('id') != $this->owner) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblog', 'artefact.blog'));
}
}
}
......@@ -283,14 +325,24 @@ class ArtefactTypeBlog extends ArtefactType {
* @param User
* @return array (count: integer, data: array)
*/
public static function get_blog_list($limit, $offset) {
public static function get_blog_list($limit, $offset, $institution = null) {
global $USER;
($result = get_records_sql_array("
SELECT b.id, b.title, b.description, b.locked, COUNT(p.id) AS postcount
FROM {artefact} b LEFT JOIN {artefact} p ON (p.parent = b.id AND p.artefacttype = 'blogpost')
WHERE b.owner = ? AND b.artefacttype = 'blog'
GROUP BY b.id, b.title, b.description, b.locked
ORDER BY b.title", array($USER->get('id')), $offset, $limit))
$sql = "SELECT b.id, b.title, b.description, b.locked, COUNT(p.id) AS postcount
FROM {artefact} b LEFT JOIN {artefact} p ON (p.parent = b.id AND p.artefacttype = 'blogpost')
WHERE b.artefacttype = 'blog'";
if ($institution) {
$sql .= ' AND b.institution = ?';
$values = array($institution);
$count = (int)get_field('artefact', 'COUNT(*)', 'institution', $institution, 'artefacttype', 'blog');
}
else {
$sql .= ' AND b.owner = ?';
$values = array($USER->get('id'));
$count = (int)get_field('artefact', 'COUNT(*)', 'owner', $USER->get('id'), 'artefacttype', 'blog');
}
$sql .= " GROUP BY b.id, b.title, b.description, b.locked ORDER BY b.title";
($result = get_records_sql_array($sql, $values, $offset, $limit))
|| ($result = array());
foreach ($result as &$r) {
......@@ -299,8 +351,6 @@ class ArtefactTypeBlog extends ArtefactType {
}
}
$count = (int)get_field('artefact', 'COUNT(*)', 'owner', $USER->get('id'), 'artefacttype', 'blog');
return array($count, $result);
}
......@@ -332,16 +382,21 @@ class ArtefactTypeBlog extends ArtefactType {
/**
* This function creates a new blog.
*
* @param User
* @param User or null
* @param array
*/
public static function new_blog(User $user, array $values) {
public static function new_blog($user, array $values) {
require_once('embeddedimage.php');
db_begin();
$artefact = new ArtefactTypeBlog();
$artefact->set('title', $values['title']);
$artefact->set('description', $values['description']);
$artefact->set('owner', $user->get('id'));
if (!empty($values['institution'])) {
$artefact->set('institution', $values['institution']);
}
else {
$artefact->set('owner', $user->get('id'));
}
$artefact->set('tags', $values['tags']);
if (get_config('licensemetadata')) {
$artefact->set('license', $values['license']);
......@@ -368,10 +423,10 @@ class ArtefactTypeBlog extends ArtefactType {
}
$artefact = new ArtefactTypeBlog($values['id']);
if ($user->get('id') != $artefact->get('owner')) {
$institution = isset($values['institution']) ? $values['institution'] : null;
if (!self::can_edit_blog($artefact, $institution)) {
return;
}
$artefact->set('title', $values['title']);
$newdescription = EmbeddedImage::prepare_embedded_images($values['description'], 'blog', $values['id']);
$artefact->set('description', $newdescription);
......@@ -514,6 +569,27 @@ class ArtefactTypeBlog extends ArtefactType {
return null;
}
/**
* Check to see if the user has permissions to edit the blog
*
* @param object $blog A blog artefact
* @param string $institution Institution name (optional)
*
* @return boolean
*/
public static function can_edit_blog($blog, $institution = null) {
global $USER;
if (
($institution == 'mahara' && $USER->get('admin'))
|| ($institution && $institution != 'mahara' && ($USER->get('admin') || $USER->is_institutional_admin($institution)))
|| ($USER->get('id') == $blog->get('owner'))
) {
return true;
}
return false;
}
}
/**
......@@ -650,8 +726,18 @@ class ArtefactTypeBlogPost extends ArtefactType {
*/
public function check_permission() {
global $USER;
if ($USER->get('id') != $this->owner) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
if (!empty($this->institution)) {
if ($this->institution == 'mahara' && !$USER->get('admin')) {
throw new AccessDeniedException(get_string('youarenotasiteadmin', 'artefact.blog'));
}
else if (!$USER->get('admin') && !$USER->is_institutional_admin($this->institution)) {
throw new AccessDeniedException(get_string('youarenotanadminof', 'artefact.blog', $this->institution));
}
}
else {
if ($USER->get('id') != $this->owner) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
}
}
}
......
......@@ -10,18 +10,27 @@
*/
define('INTERNAL', 1);
define('MENUITEM', 'content/blogs');
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'blog');
define('SECTION_PAGE', 'new');
require(dirname(dirname(dirname(dirname(__FILE__)))) . '/init.php');
define('TITLE', get_string('newblog','artefact.blog') . ': ' . get_string('blogsettings','artefact.blog'));
require_once('license.php');
require_once('pieforms/pieform.php');
safe_require('artefact', 'blog');
$section = false;
if ($institutionname = param_alphanum('institution', null)) {
require_once(get_config('libroot') . 'institution.php');
$section = 'institution';
if ($institutionname == 'mahara') {
$section = 'site';
}
PluginArtefactBlog::set_blog_nav(true, $institutionname);
}
$title = ($section == 'institution') ? get_string('newblog' . $section, 'artefact.blog', institution_display_name($institutionname)) : get_string('newblog' . $section,'artefact.blog');
define('TITLE', $title . ': ' . get_string('blogsettings','artefact.blog'));
$form = pieform(array(
$form = array(
'name' => 'newblog',
'method' => 'post',
'action' => '',
......@@ -64,7 +73,10 @@ $form = pieform(array(
)
)
)
));
);
$form['elements']['institution'] = array('type' => 'hidden', 'value' => ($institutionname) ? $institutionname : 0);
$form = pieform($form);
$smarty =& smarty();
$smarty->assign_by_ref('form', $form);
......@@ -80,13 +92,26 @@ exit;
function newblog_submit(Pieform $form, $values) {
global $USER;
ArtefactTypeBlog::new_blog($USER, $values);
redirect('/artefact/blog/index.php');
$data = $form->get_element('institution');
if ($data['value'] != false) {
ArtefactTypeBlog::new_blog(null, $values);
redirect('/artefact/blog/index.php?institution=' . $data['value']);
}
else {
ArtefactTypeBlog::new_blog($USER, $values);
redirect('/artefact/blog/index.php');
}
}
/**
* This function gets called to cancel a submission.
*/
function newblog_cancel_submit() {
redirect('/artefact/blog/index.php');
function newblog_cancel_submit(Pieform $form) {
$data = $form->get_element('institution');
if ($data['value'] != false) {
redirect('/artefact/blog/index.php?institution=' . $data['value']);
}
else {
redirect('/artefact/blog/index.php');
}
}
......@@ -10,7 +10,6 @@
*/
define('INTERNAL', 1);
define('MENUITEM', 'content/blogs');
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'blog');
define('SECTION_PAGE', 'post');
......@@ -36,12 +35,9 @@ if (!$blogpost) {
*/
$tagselect = param_variable('tagselect', '');
$blog = param_integer('blog');
if (!get_record('artefact', 'id', $blog, 'owner', $USER->get('id'))) {
// Blog security is also checked closer to when blogs are added, this
// check ensures that malicious users do not even see the screen for
// adding a post to a blog that is not theirs
throw new AccessDeniedException(get_string('youarenottheownerofthisblog', 'artefact.blog'));
}
$blogobj = new ArtefactTypeBlog($blog);
$blogobj->check_permission();
$title = '';
$description = '';
$tags = array($tagselect);
......@@ -68,6 +64,14 @@ else {
define('TITLE', get_string('editblogpost','artefact.blog'));
}
$institution = $institutionname = null;
$blogobj = new ArtefactTypeBlog($blog);
if ($blogobj->get('institution')) {
$institution = true;
$institutionname = $blogobj->get('institution');
}
PluginArtefactBlog::set_blog_nav($institution, $institutionname);
$folder = param_integer('folder', 0);
$browse = (int) param_variable('browse', 0);
$highlight = null;
......@@ -208,7 +212,13 @@ $smarty->display('artefact:blog:editpost.tpl');
*/
function editpost_cancel_submit() {
global $blog;
redirect(get_config('wwwroot') . 'artefact/blog/view/index.php?id=' . $blog);
$blogobj = new ArtefactTypeBlog($blog);
if ($blogobj->get('institution')) {
redirect(get_config('wwwroot') . 'artefact/blog/view/index.php?id=' . $blog . '&institution=' . $blogobj->get('institution'));
}
else {
redirect(get_config('wwwroot') . 'artefact/blog/view/index.php?id=' . $blog);
}
}
function editpost_submit(Pieform $form, $values) {
......@@ -229,7 +239,13 @@ function editpost_submit(Pieform $form, $values) {
$postobj->set('allowcomments', (int) $values['allowcomments']);
if (!$blogpost) {
$postobj->set('parent', $blog);
$postobj->set('owner', $USER->id);
$blogobj = new ArtefactTypeBlog($blog);
if ($blogobj->get('institution')) {
$postobj->set('institution', $blogobj->get('institution'));
}
else {
$postobj->set('owner', $USER->id);
}
}
$postobj->commit();
$blogpost = $postobj->get('id');
......
......@@ -10,7 +10,6 @@
*/
define('INTERNAL', 1);
define('MENUITEM', 'content/blogs');
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'blog');
define('SECTION_PAGE', 'settings');
......@@ -26,6 +25,15 @@ if (!PluginArtefactBlog::is_active()) {
$id = param_integer('id');
$blog = new ArtefactTypeBlog($id);
$institution = $institutionname = null;
if ($blog->get('institution')) {
$institution = true;
$institutionname = $blog->get('institution');
}