Commit 1d6f041a authored by Peter's avatar Peter
Browse files

MDL-66120 block_community: Remove community block and related caps

With the sunsetting of moodle.net, the community block will no longer
be functional, so removing the block and related caps
parent 310d6901
...@@ -20,12 +20,12 @@ Feature: Edit capabilities ...@@ -20,12 +20,12 @@ Feature: Edit capabilities
And I set the following system permissions of "Teacher" role: And I set the following system permissions of "Teacher" role:
| capability | permission | | capability | permission |
| block/mnet_hosts:myaddinstance | Allow | | block/mnet_hosts:myaddinstance | Allow |
| moodle/community:add | Inherit | | moodle/site:messageanyuser | Inherit |
| moodle/grade:managesharedforms | Prevent | | moodle/grade:managesharedforms | Prevent |
| moodle/course:request | Prohibit | | moodle/course:request | Prohibit |
When I follow "Edit Teacher role" When I follow "Edit Teacher role"
Then "block/mnet_hosts:myaddinstance" capability has "Allow" permission Then "block/mnet_hosts:myaddinstance" capability has "Allow" permission
And "moodle/community:add" capability has "Not set" permission And "moodle/site:messageanyuser" capability has "Not set" permission
And "moodle/grade:managesharedforms" capability has "Prevent" permission And "moodle/grade:managesharedforms" capability has "Prevent" permission
And "moodle/course:request" capability has "Prohibit" permission And "moodle/course:request" capability has "Prohibit" permission
......
...@@ -20,7 +20,7 @@ Feature: Restore Moodle 2 course backups ...@@ -20,7 +20,7 @@ Feature: Restore Moodle 2 course backups
And I add a "Forum" to section "1" and I fill the form with: And I add a "Forum" to section "1" and I fill the form with:
| Forum name | Test forum name | | Forum name | Test forum name |
| Description | Test forum description | | Description | Test forum description |
And I add the "Community finder" block And I add the "Activities" block
@javascript @javascript
Scenario: Restore a course in another existing course Scenario: Restore a course in another existing course
...@@ -28,7 +28,7 @@ Feature: Restore Moodle 2 course backups ...@@ -28,7 +28,7 @@ Feature: Restore Moodle 2 course backups
| Confirmation | Filename | test_backup.mbz | | Confirmation | Filename | test_backup.mbz |
And I restore "test_backup.mbz" backup into "Course 2" course using this options: And I restore "test_backup.mbz" backup into "Course 2" course using this options:
Then I should see "Course 2" Then I should see "Course 2"
And I should see "Community finder" in the "Community finder" "block" And I should see "Activities" in the "Activities" "block"
And I should see "Test forum name" And I should see "Test forum name"
@javascript @javascript
...@@ -38,7 +38,7 @@ Feature: Restore Moodle 2 course backups ...@@ -38,7 +38,7 @@ Feature: Restore Moodle 2 course backups
And I restore "test_backup.mbz" backup into a new course using this options: And I restore "test_backup.mbz" backup into a new course using this options:
| Schema | Course name | Course 1 restored in a new course | | Schema | Course name | Course 1 restored in a new course |
Then I should see "Course 1 restored in a new course" Then I should see "Course 1 restored in a new course"
And I should see "Community finder" in the "Community finder" "block" And I should see "Activities" in the "Activities" "block"
And I should see "Test forum name" And I should see "Test forum name"
And I should see "Topic 15" And I should see "Topic 15"
And I should not see "Topic 16" And I should not see "Topic 16"
...@@ -72,7 +72,7 @@ Feature: Restore Moodle 2 course backups ...@@ -72,7 +72,7 @@ Feature: Restore Moodle 2 course backups
Then I should see "Course 1" Then I should see "Course 1"
And I should not see "Section 3" And I should not see "Section 3"
And I should not see "Test forum post backup name" And I should not see "Test forum post backup name"
And I should see "Community finder" in the "Community finder" "block" And I should see "Activities" in the "Activities" "block"
And I should see "Test forum name" And I should see "Test forum name"
@javascript @javascript
......
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package block_community
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
*
* The community block
*/
class block_community extends block_list {
function init() {
$this->title = get_string('pluginname', 'block_community');
}
function user_can_addto($page) {
// Don't allow people to add the block if they can't even use it
if (!has_capability('moodle/community:add', $page->context)) {
return false;
}
return parent::user_can_addto($page);
}
function user_can_edit() {
// Don't allow people to edit the block if they can't even use it
if (!has_capability('moodle/community:add',
context::instance_by_id($this->instance->parentcontextid))) {
return false;
}
return parent::user_can_edit();
}
function get_content() {
global $CFG, $OUTPUT, $USER;
$coursecontext = context::instance_by_id($this->instance->parentcontextid);
if (!has_capability('moodle/community:add', $coursecontext)
or $this->content !== NULL) {
return $this->content;
}
$this->content = new stdClass();
$this->content->items = array();
$this->content->icons = array();
$this->content->footer = '';
if (!isloggedin()) {
return $this->content;
}
$icon = $OUTPUT->pix_icon('i/group', get_string('group'));
$addcourseurl = new moodle_url('/blocks/community/communitycourse.php',
array('add' => true, 'courseid' => $this->page->course->id));
$searchlink = html_writer::tag('a', $icon . get_string('addcourse', 'block_community'),
array('href' => $addcourseurl->out(false)));
$this->content->items[] = $searchlink;
require_once($CFG->dirroot . '/blocks/community/locallib.php');
$communitymanager = new block_community_manager();
$courses = $communitymanager->block_community_get_courses($USER->id);
if ($courses) {
$this->content->items[] = html_writer::empty_tag('hr');
$this->content->icons[] = '';
$this->content->items[] = get_string('mycommunities', 'block_community');
$this->content->icons[] = '';
foreach ($courses as $course) {
//delete link
$deleteicon = $OUTPUT->pix_icon('t/delete', get_string('removecommunitycourse', 'block_community'));
$deleteurl = new moodle_url('/blocks/community/communitycourse.php',
array('remove' => true,
'courseid' => $this->page->course->id,
'communityid' => $course->id, 'sesskey' => sesskey()));
$deleteatag = html_writer::tag('a', $deleteicon, array('href' => $deleteurl));
$courselink = html_writer::tag('a', $course->coursename,
array('href' => $course->courseurl));
$this->content->items[] = $courselink . ' ' . $deleteatag;
$this->content->icons[] = '';
}
}
return $this->content;
}
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for block_community.
*
* @package block_community
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace block_community\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\writer;
use core_privacy\local\request\deletion_criteria;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\userlist;
use core_privacy\local\request\approved_userlist;
/**
* Privacy Subsystem implementation for block_community.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\core_userlist_provider,
\core_privacy\local\request\plugin\provider {
/**
* Returns information about how block_community stores its data.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) : collection {
$collection->add_database_table(
'block_community',
[
'coursename' => 'privacy:metadata:block_community:coursename',
'coursedescription' => 'privacy:metadata:block_community:coursedescription',
'courseurl' => 'privacy:metadata:block_community:courseurl',
'imageurl' => 'privacy:metadata:block_community:imageurl',
'userid' => 'privacy:metadata:block_community:userid',
],
'privacy:metadata:block_community'
);
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
$contextlist = new \core_privacy\local\request\contextlist();
// The block_community data is associated at the user context level, so retrieve the user's context id.
$sql = "SELECT c.id
FROM {block_community} bc
JOIN {context} c ON c.instanceid = bc.userid AND c.contextlevel = :contextuser
WHERE bc.userid = :userid
GROUP BY c.id";
$params = [
'contextuser' => CONTEXT_USER,
'userid' => $userid
];
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Get the list of users within a specific context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();
if (!$context instanceof \context_user) {
return;
}
$sql = "SELECT userid
FROM {block_community}
WHERE userid = ?";
$params = [$context->instanceid];
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Export all user data for the specified user using the User context level.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
// If the user has block_community data, then only the User context should be present so get the first context.
$contexts = $contextlist->get_contexts();
if (count($contexts) == 0) {
return;
}
$context = reset($contexts);
// Sanity check that context is at the User context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
// The block_community data export is organised in: {User Context}/Community Finder/My communities/data.json.
$subcontext = [
get_string('pluginname', 'block_community'),
get_string('mycommunities', 'block_community')
];
$sql = "SELECT bc.id as id,
bc.coursename as name,
bc.coursedescription as description,
bc.courseurl as url,
bc.imageurl as imageurl
FROM {block_community} bc
WHERE bc.userid = :userid
ORDER BY bc.coursename";
$params = [
'userid' => $userid
];
$communities = $DB->get_records_sql($sql, $params);
$data = (object) [
'communities' => $communities
];
writer::with_context($context)->export_data($subcontext, $data);
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
global $DB;
// Sanity check that context is at the User context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
$DB->delete_records('block_community', ['userid' => $userid]);
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
global $DB;
$context = $userlist->get_context();
if ($context instanceof \context_user) {
$DB->delete_records('block_community', ['userid' => $context->instanceid]);
}
}
/**
* Delete all user data for the specified user.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
// If the user has block_community data, then only the User context should be present so get the first context.
$contexts = $contextlist->get_contexts();
if (count($contexts) == 0) {
return;
}
$context = reset($contexts);
// Sanity check that context is at the User context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
$DB->delete_records('block_community', ['userid' => $userid]);
}
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Controller for various actions of the block.
*
* This page display the community course search form.
* It also handles adding a course to the community block.
* It also handles downloading a course template.
*
* @package block_community
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
*/
require('../../config.php');
require_once($CFG->dirroot . '/blocks/community/locallib.php');
require_once($CFG->dirroot . '/blocks/community/forms.php');
require_login();
$courseid = required_param('courseid', PARAM_INT); //if no courseid is given
$parentcourse = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
$context = context_course::instance($courseid);
$PAGE->set_course($parentcourse);
$PAGE->set_url('/blocks/community/communitycourse.php');
$PAGE->set_heading($SITE->fullname);
$PAGE->set_pagelayout('incourse');
$PAGE->set_title(get_string('searchcourse', 'block_community'));
$PAGE->navbar->add(get_string('searchcourse', 'block_community'));
$search = optional_param('search', null, PARAM_TEXT);
//if no capability to search course, display an error message
require_capability('moodle/community:add', $context);
$usercandownload = has_capability('moodle/community:download', $context);
$communitymanager = new block_community_manager();
$renderer = $PAGE->get_renderer('block_community');
/// Check if the page has been called with trust argument
$add = optional_param('add', -1, PARAM_INT);
$confirm = optional_param('confirmed', false, PARAM_INT);
if ($add != -1 and $confirm and confirm_sesskey()) {
$course = new stdClass();
$course->name = optional_param('coursefullname', '', PARAM_TEXT);
$course->description = optional_param('coursedescription', '', PARAM_TEXT);
$course->url = optional_param('courseurl', '', PARAM_URL);
$course->imageurl = optional_param('courseimageurl', '', PARAM_URL);
$communitymanager->block_community_add_course($course, $USER->id);
echo $OUTPUT->header();
echo $renderer->save_link_success(
new moodle_url('/course/view.php', array('id' => $courseid)));
echo $OUTPUT->footer();
die();
}
/// Delete temp file when cancel restore
$cancelrestore = optional_param('cancelrestore', false, PARAM_INT);
if ($usercandownload and $cancelrestore and confirm_sesskey()) {
$filename = optional_param('filename', '', PARAM_ALPHANUMEXT);
//delete temp file
$backuptempdir = make_backup_temp_directory('');
unlink($backuptempdir . '/' . $filename . ".mbz");
}
/// Download
$download = optional_param('download', -1, PARAM_INT);
$downloadcourseid = optional_param('downloadcourseid', '', PARAM_INT);
$coursefullname = optional_param('coursefullname', '', PARAM_ALPHANUMEXT);
$backupsize = optional_param('backupsize', 0, PARAM_INT);
if ($usercandownload and $download != -1 and !empty($downloadcourseid) and confirm_sesskey()) {
//OUTPUT: display restore choice page
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('downloadingcourse', 'block_community'), 3, 'main');
$sizeinfo = new stdClass();
$sizeinfo->total = number_format($backupsize / 1000000, 2);
echo html_writer::tag('div', get_string('downloadingsize', 'block_community', $sizeinfo),
array('class' => 'textinfo'));
if (ob_get_level()) {
ob_flush();
}
flush();
list($privatefilename, $tmpfilename) = \core\hub\publication::download_course_backup($downloadcourseid, $coursefullname);
echo html_writer::tag('div', get_string('downloaded', 'block_community'),
array('class' => 'textinfo'));
echo $OUTPUT->notification(get_string('downloadconfirmed', 'block_community',
$privatefilename), 'notifysuccess');
echo $renderer->restore_confirmation_box($tmpfilename, $context);
echo $OUTPUT->footer();
die();
}
/// Remove community
$remove = optional_param('remove', '', PARAM_INT);
$communityid = optional_param('communityid', '', PARAM_INT);
if ($remove != -1 and !empty($communityid) and confirm_sesskey()) {
$communitymanager->block_community_remove_course($communityid, $USER->id);
echo $OUTPUT->header();
echo $renderer->remove_success(new moodle_url('/course/view.php', array('id' => $courseid)));
echo $OUTPUT->footer();
die();
}
//Get form default/current values
$fromformdata['coverage'] = optional_param('coverage', 'all', PARAM_TEXT);
$fromformdata['licence'] = optional_param('licence', 'all', PARAM_ALPHANUMEXT);
$fromformdata['subject'] = optional_param('subject', 'all', PARAM_ALPHANUMEXT);
$fromformdata['audience'] = optional_param('audience', 'all', PARAM_ALPHANUMEXT);
$fromformdata['language'] = optional_param('language', current_language(), PARAM_ALPHANUMEXT);
$fromformdata['educationallevel'] = optional_param('educationallevel', 'all', PARAM_ALPHANUMEXT);
$fromformdata['downloadable'] = optional_param('downloadable', $usercandownload, PARAM_ALPHANUM);
$fromformdata['orderby'] = optional_param('orderby', 'newest', PARAM_ALPHA);
$fromformdata['search'] = $search;
$fromformdata['courseid'] = $courseid;
$hubselectorform = new community_hub_search_form('', $fromformdata);
$hubselectorform->set_data($fromformdata);
//Retrieve courses by web service
$courses = null;
if (optional_param('executesearch', 0, PARAM_INT) and confirm_sesskey()) {
$downloadable = optional_param('downloadable', false, PARAM_INT);
$options = new stdClass();
if (!empty($fromformdata['coverage'])) {
$options->coverage = $fromformdata['coverage'];
}
if ($fromformdata['licence'] != 'all') {
$options->licenceshortname = $fromformdata['licence'];
}
if ($fromformdata['subject'] != 'all') {
$options->subject = $fromformdata['subject'];
}
if ($fromformdata['audience'] != 'all') {
$options->audience = $fromformdata['audience'];
}
if ($fromformdata['educationallevel'] != 'all') {
$options->educationallevel = $fromformdata['educationallevel'];
}
if ($fromformdata['language'] != 'all') {
$options->language = $fromformdata['language'];
}
$options->orderby = $fromformdata['orderby'];
//the range of course requested
$options->givememore = optional_param('givememore', 0, PARAM_INT);
list($courses, $coursetotal) = \core\hub\publication::search($search, $downloadable, $options);
}
// OUTPUT
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('searchcommunitycourse', 'block_community'), 3, 'main');
echo $renderer->moodlenet_info();
$hubselectorform->display();
if (!empty($errormessage)) {
echo $errormessage;
}
//load javascript
$commentedcourseids = array(); //result courses with comments only
$courseids = array(); //all result courses
$courseimagenumbers = array(); //number of screenshots of all courses (must be exact same order than $courseids)
if (!empty($courses)) {
foreach ($courses as $course) {
if (!empty($course['comments'])) {
$commentedcourseids[] = $course['id'];
}
$courseids[] = $course['id'];
$courseimagenumbers[] = $course['screenshots'];
}
}
$PAGE->requires->yui_module('moodle-block_community-comments', 'M.blocks_community.init_comments',
array(array('commentids' => $commentedcourseids, 'closeButtonTitle' => get_string('close', 'editor'))));
$PAGE->requires->yui_module('moodle-block_community-imagegallery', 'M.blocks_community.init_imagegallery',
array(array('imageids' => $courseids, 'imagenumbers' => $courseimagenumbers,
'huburl' => HUB_MOODLEORGHUBURL, 'closeButtonTitle' => get_string('close', 'editor'))));
echo highlight($search, $renderer->course_list($courses, null, $courseid));
//display givememore/Next link if more course can be displayed
if (!empty($courses)) {
if (($options->givememore + count($courses)) < $coursetotal) {
$fromformdata['givememore'] = count($courses) + $options->givememore;
$fromformdata['executesearch'] = true;
$fromformdata['sesskey'] = sesskey();
echo $renderer->next_button($fromformdata);