2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 * The main interface for recycle bin methods.
20 * @package tool_recyclebin
21 * @copyright 2015 University of Kent
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 namespace tool_recyclebin;
27 defined('MOODLE_INTERNAL') || die();
29 define('TOOL_RECYCLEBIN_COURSE_BIN_FILEAREA', 'recyclebin_course');
32 * Represents a course's recyclebin.
34 * @package tool_recyclebin
35 * @copyright 2015 University of Kent
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 class course_bin extends base_bin {
41 * @var int The course id.
48 * @param int $courseid Course ID.
50 public function __construct($courseid) {
51 $this->_courseid = $courseid;
55 * Is this recyclebin enabled?
57 * @return bool true if enabled, false if not.
59 public static function is_enabled() {
60 return get_config('tool_recyclebin', 'coursebinenable');
64 * Returns an item from the recycle bin.
66 * @param int $itemid Item ID to retrieve.
67 * @return \stdClass the item.
69 public function get_item($itemid) {
72 return $DB->get_record('tool_recyclebin_course', array(
78 * Returns a list of items in the recycle bin for this course.
80 * @return array the list of items.
82 public function get_items() {
85 return $DB->get_records('tool_recyclebin_course', array(
86 'courseid' => $this->_courseid
91 * Store a course module in the recycle bin.
93 * @param \stdClass $cm Course module
94 * @throws \moodle_exception
96 public function store_item($cm) {
99 require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
101 // Get more information.
102 $modinfo = get_fast_modinfo($cm->course);
104 if (!isset($modinfo->cms[$cm->id])) {
105 return; // Can't continue without the module information.
108 $cminfo = $modinfo->cms[$cm->id];
110 // Check backup/restore support.
111 if (!plugin_supports('mod', $cminfo->modname , FEATURE_BACKUP_MOODLE2)) {
115 // Backup the activity.
117 $controller = new \backup_controller(
118 \backup::TYPE_1ACTIVITY,
120 \backup::FORMAT_MOODLE,
121 \backup::INTERACTIVE_NO,
122 \backup::MODE_GENERAL,
125 $controller->execute_plan();
128 $result = $controller->get_results();
129 if (!isset($result['backup_destination'])) {
130 throw new \moodle_exception('Failed to backup activity prior to deletion.');
133 // Have finished with the controller, let's destroy it, freeing mem and resources.
134 $controller->destroy();
136 // Grab the filename.
137 $file = $result['backup_destination'];
138 if (!$file->get_contenthash()) {
139 throw new \moodle_exception('Failed to backup activity prior to deletion (invalid file).');
142 // Record the activity, get an ID.
143 $activity = new \stdClass();
144 $activity->courseid = $cm->course;
145 $activity->section = $cm->section;
146 $activity->module = $cm->module;
147 $activity->name = $cminfo->name;
148 $activity->timecreated = time();
149 $binid = $DB->insert_record('tool_recyclebin_course', $activity);
151 // Create the location we want to copy this file to.
153 'contextid' => \context_course::instance($this->_courseid)->id,
154 'component' => 'tool_recyclebin',
155 'filearea' => TOOL_RECYCLEBIN_COURSE_BIN_FILEAREA,
157 'timemodified' => time()
160 // Move the file to our own special little place.
161 $fs = get_file_storage();
162 if (!$fs->create_file_from_storedfile($filerecord, $file)) {
163 // Failed, cleanup first.
164 $DB->delete_records('tool_recyclebin_course', array(
168 throw new \moodle_exception("Failed to copy backup file to recyclebin.");
171 // Delete the old file.
175 $event = \tool_recyclebin\event\course_bin_item_created::create(array(
176 'objectid' => $binid,
177 'context' => \context_course::instance($cm->course)
183 * Restore an item from the recycle bin.
185 * @param \stdClass $item The item database record
186 * @throws \moodle_exception
188 public function restore_item($item) {
189 global $CFG, $OUTPUT, $PAGE;
191 require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
195 // Grab the course context.
196 $context = \context_course::instance($this->_courseid);
199 $fs = get_file_storage();
200 $files = $fs->get_area_files($context->id, 'tool_recyclebin', TOOL_RECYCLEBIN_COURSE_BIN_FILEAREA, $item->id,
201 'itemid, filepath, filename', false);
204 throw new \moodle_exception('Invalid recycle bin item!');
207 if (count($files) > 1) {
208 throw new \moodle_exception('Too many files found!');
211 // Get the backup file.
212 $file = reset($files);
214 // Get a temp directory name and create it.
215 $tempdir = \restore_controller::get_tempdir_name($context->id, $user->id);
216 $fulltempdir = make_temp_directory('/backup/' . $tempdir);
218 // Extract the backup to tempdir.
219 $fb = get_file_packer('application/vnd.moodle.backup');
220 $fb->extract_to_pathname($file, $fulltempdir);
222 // Define the import.
223 $controller = new \restore_controller(
226 \backup::INTERACTIVE_NO,
227 \backup::MODE_GENERAL,
229 \backup::TARGET_EXISTING_ADDING
233 if (!$controller->execute_precheck()) {
234 $results = $controller->get_precheck_results();
236 // If errors are found then delete the file we created.
237 if (!empty($results['errors'])) {
238 fulldelete($fulltempdir);
240 echo $OUTPUT->header();
241 $backuprenderer = $PAGE->get_renderer('core', 'backup');
242 echo $backuprenderer->precheck_notices($results);
243 echo $OUTPUT->continue_button(new \moodle_url('/course/view.php', array('id' => $this->_courseid)));
244 echo $OUTPUT->footer();
250 $controller->execute_plan();
252 // Have finished with the controller, let's destroy it, freeing mem and resources.
253 $controller->destroy();
256 $event = \tool_recyclebin\event\course_bin_item_restored::create(array(
257 'objectid' => $item->id,
258 'context' => $context
260 $event->add_record_snapshot('tool_recyclebin_course', $item);
264 fulldelete($fulltempdir);
265 $this->delete_item($item);
269 * Delete an item from the recycle bin.
271 * @param \stdClass $item The item database record
273 public function delete_item($item) {
276 // Grab the course context.
277 $context = \context_course::instance($this->_courseid);
280 $fs = get_file_storage();
281 $files = $fs->get_area_files($context->id, 'tool_recyclebin', TOOL_RECYCLEBIN_COURSE_BIN_FILEAREA, $item->id);
282 foreach ($files as $file) {
286 // Delete the record.
287 $DB->delete_records('tool_recyclebin_course', array(
291 // The course might have been deleted, check we have a context.
292 $context = \context_course::instance($item->courseid, \IGNORE_MISSING);
298 $event = \tool_recyclebin\event\course_bin_item_deleted::create(array(
299 'objectid' => $item->id,
300 'context' => $context
302 $event->add_record_snapshot('tool_recyclebin_course', $item);
307 * Can we view items in this recycle bin?
309 * @return bool returns true if they can view, false if not
311 public function can_view() {
312 $context = \context_course::instance($this->_courseid);
313 return has_capability('tool/recyclebin:viewitems', $context);
317 * Can we restore items in this recycle bin?
319 * @return bool returns true if they can restore, false if not
321 public function can_restore() {
322 $context = \context_course::instance($this->_courseid);
323 return has_capability('tool/recyclebin:restoreitems', $context);
327 * Can we delete this?
329 * @return bool returns true if they can delete, false if not
331 public function can_delete() {
332 $context = \context_course::instance($this->_courseid);
333 return has_capability('tool/recyclebin:deleteitems', $context);