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_COURSECAT_BIN_FILEAREA', 'recyclebin_coursecat');
32 * Represents a category'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 category_bin extends base_bin {
41 * @var int The category id.
43 protected $_categoryid;
48 * @param int $categoryid The category id.
50 public function __construct($categoryid) {
51 $this->_categoryid = $categoryid;
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', 'categorybinenable');
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 $item = $DB->get_record('tool_recyclebin_category', array(
76 $item->name = get_course_display_name_for_list($item);
82 * Returns a list of items in the recycle bin for this course.
84 * @return array the list of items.
86 public function get_items() {
89 $items = $DB->get_records('tool_recyclebin_category', array(
90 'categoryid' => $this->_categoryid
93 foreach ($items as $item) {
94 $item->name = get_course_display_name_for_list($item);
101 * Store a course in the recycle bin.
103 * @param \stdClass $course Course
104 * @throws \moodle_exception
106 public function store_item($course) {
109 require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
111 // Backup the course.
113 $controller = new \backup_controller(
114 \backup::TYPE_1COURSE,
116 \backup::FORMAT_MOODLE,
117 \backup::INTERACTIVE_NO,
118 \backup::MODE_GENERAL,
121 $controller->execute_plan();
124 $result = $controller->get_results();
125 if (!isset($result['backup_destination'])) {
126 throw new \moodle_exception('Failed to backup activity prior to deletion.');
129 // Have finished with the controller, let's destroy it, freeing mem and resources.
130 $controller->destroy();
132 // Grab the filename.
133 $file = $result['backup_destination'];
134 if (!$file->get_contenthash()) {
135 throw new \moodle_exception('Failed to backup activity prior to deletion (invalid file).');
138 // Record the activity, get an ID.
139 $item = new \stdClass();
140 $item->categoryid = $course->category;
141 $item->shortname = $course->shortname;
142 $item->fullname = $course->fullname;
143 $item->timecreated = time();
144 $binid = $DB->insert_record('tool_recyclebin_category', $item);
146 // Create the location we want to copy this file to.
148 'contextid' => \context_coursecat::instance($course->category)->id,
149 'component' => 'tool_recyclebin',
150 'filearea' => TOOL_RECYCLEBIN_COURSECAT_BIN_FILEAREA,
152 'timemodified' => time()
155 // Move the file to our own special little place.
156 $fs = get_file_storage();
157 if (!$fs->create_file_from_storedfile($filerecord, $file)) {
158 // Failed, cleanup first.
159 $DB->delete_records('tool_recyclebin_category', array(
163 throw new \moodle_exception("Failed to copy backup file to recyclebin.");
166 // Delete the old file.
170 $event = \tool_recyclebin\event\category_bin_item_created::create(array(
171 'objectid' => $binid,
172 'context' => \context_coursecat::instance($course->category)
178 * Restore an item from the recycle bin.
180 * @param \stdClass $item The item database record
181 * @throws \moodle_exception
183 public function restore_item($item) {
184 global $CFG, $OUTPUT, $PAGE;
186 require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
187 require_once($CFG->dirroot . '/course/lib.php');
191 // Grab the course category context.
192 $context = \context_coursecat::instance($this->_categoryid);
194 // Get the backup file.
195 $fs = get_file_storage();
196 $files = $fs->get_area_files($context->id, 'tool_recyclebin', TOOL_RECYCLEBIN_COURSECAT_BIN_FILEAREA, $item->id,
197 'itemid, filepath, filename', false);
200 throw new \moodle_exception('Invalid recycle bin item!');
203 if (count($files) > 1) {
204 throw new \moodle_exception('Too many files found!');
207 // Get the backup file.
208 $file = reset($files);
210 // Get a temp directory name and create it.
211 $tempdir = \restore_controller::get_tempdir_name($context->id, $user->id);
212 $fulltempdir = make_temp_directory('/backup/' . $tempdir);
214 // Extract the backup to tmpdir.
215 $fb = get_file_packer('application/vnd.moodle.backup');
216 $fb->extract_to_pathname($file, $fulltempdir);
219 $course = new \stdClass();
220 $course->category = $this->_categoryid;
221 $course->shortname = $item->shortname;
222 $course->fullname = $item->fullname;
223 $course->summary = '';
225 // Create a new course.
226 $course = create_course($course);
228 throw new \moodle_exception("Could not create course to restore into.");
231 // Define the import.
232 $controller = new \restore_controller(
235 \backup::INTERACTIVE_NO,
236 \backup::MODE_GENERAL,
238 \backup::TARGET_NEW_COURSE
242 if (!$controller->execute_precheck()) {
243 $results = $controller->get_precheck_results();
245 // Check if errors have been found.
246 if (!empty($results['errors'])) {
247 // Delete the temporary file we created.
248 fulldelete($fulltempdir);
250 // Delete the course we created.
251 delete_course($course, false);
253 echo $OUTPUT->header();
254 $backuprenderer = $PAGE->get_renderer('core', 'backup');
255 echo $backuprenderer->precheck_notices($results);
256 echo $OUTPUT->continue_button(new \moodle_url('/course/index.php', array('categoryid' => $this->_categoryid)));
257 echo $OUTPUT->footer();
263 $controller->execute_plan();
265 // Have finished with the controller, let's destroy it, freeing mem and resources.
266 $controller->destroy();
269 $event = \tool_recyclebin\event\category_bin_item_restored::create(array(
270 'objectid' => $item->id,
271 'context' => $context
273 $event->add_record_snapshot('tool_recyclebin_category', $item);
277 fulldelete($fulltempdir);
278 $this->delete_item($item);
282 * Delete an item from the recycle bin.
284 * @param \stdClass $item The item database record
285 * @throws \coding_exception
287 public function delete_item($item) {
290 // Grab the course category context.
291 $context = \context_coursecat::instance($this->_categoryid);
294 $fs = get_file_storage();
295 $files = $fs->get_area_files($context->id, 'tool_recyclebin', TOOL_RECYCLEBIN_COURSECAT_BIN_FILEAREA, $item->id);
296 foreach ($files as $file) {
300 // Delete the record.
301 $DB->delete_records('tool_recyclebin_category', array(
306 $event = \tool_recyclebin\event\category_bin_item_deleted::create(array(
307 'objectid' => $item->id,
308 'context' => \context_coursecat::instance($item->categoryid)
310 $event->add_record_snapshot('tool_recyclebin_category', $item);
315 * Can we view items in this recycle bin?
317 * @return bool returns true if they can view, false if not
319 public function can_view() {
320 $context = \context_coursecat::instance($this->_categoryid);
321 return has_capability('tool/recyclebin:viewitems', $context);
325 * Can we restore items in this recycle bin?
327 * @return bool returns true if they can restore, false if not
329 public function can_restore() {
330 $context = \context_coursecat::instance($this->_categoryid);
331 return has_capability('tool/recyclebin:restoreitems', $context);
335 * Can we delete items in this recycle bin?
337 * @return bool returns true if they can delete, false if not
339 public function can_delete() {
340 $context = \context_coursecat::instance($this->_categoryid);
341 return has_capability('tool/recyclebin:deleteitems', $context);