06b06de1601d4ab2f564bca8cd825ddce5b6ffcf
[moodle.git] / admin / tool / recyclebin / classes / category_bin.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
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.
8 //
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.
13 //
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/>.
17 /**
18  * The main interface for recycle bin methods.
19  *
20  * @package    tool_recyclebin
21  * @copyright  2015 University of Kent
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 namespace tool_recyclebin;
27 defined('MOODLE_INTERNAL') || die();
29 define('TOOL_RECYCLEBIN_COURSECAT_BIN_FILEAREA', 'recyclebin_coursecat');
31 /**
32  * Represents a category's recyclebin.
33  *
34  * @package    tool_recyclebin
35  * @copyright  2015 University of Kent
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class category_bin extends base_bin {
40     /**
41      * @var int The category id.
42      */
43     protected $_categoryid;
45     /**
46      * Constructor.
47      *
48      * @param int $categoryid The category id.
49      */
50     public function __construct($categoryid) {
51         $this->_categoryid = $categoryid;
52     }
54     /**
55      * Is this recyclebin enabled?
56      *
57      * @return bool true if enabled, false if not.
58      */
59     public static function is_enabled() {
60         return get_config('tool_recyclebin', 'categorybinenable');
61     }
63     /**
64      * Returns an item from the recycle bin.
65      *
66      * @param int $itemid Item ID to retrieve.
67      * @return \stdClass the item.
68      */
69     public function get_item($itemid) {
70         global $DB;
72         $item = $DB->get_record('tool_recyclebin_category', array(
73             'id' => $itemid
74         ), '*', MUST_EXIST);
76         $item->name = get_course_display_name_for_list($item);
78         return $item;
79     }
81     /**
82      * Returns a list of items in the recycle bin for this course.
83      *
84      * @return array the list of items.
85      */
86     public function get_items() {
87         global $DB;
89         $items = $DB->get_records('tool_recyclebin_category', array(
90             'categoryid' => $this->_categoryid
91         ));
93         foreach ($items as $item) {
94             $item->name = get_course_display_name_for_list($item);
95         }
97         return $items;
98     }
100     /**
101      * Store a course in the recycle bin.
102      *
103      * @param \stdClass $course Course
104      * @throws \moodle_exception
105      */
106     public function store_item($course) {
107         global $CFG, $DB;
109         require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
111         // Backup the course.
112         $user = get_admin();
113         $controller = new \backup_controller(
114             \backup::TYPE_1COURSE,
115             $course->id,
116             \backup::FORMAT_MOODLE,
117             \backup::INTERACTIVE_NO,
118             \backup::MODE_GENERAL,
119             $user->id
120         );
121         $controller->execute_plan();
123         // Grab the result.
124         $result = $controller->get_results();
125         if (!isset($result['backup_destination'])) {
126             throw new \moodle_exception('Failed to backup activity prior to deletion.');
127         }
129         // Grab the filename.
130         $file = $result['backup_destination'];
131         if (!$file->get_contenthash()) {
132             throw new \moodle_exception('Failed to backup activity prior to deletion (invalid file).');
133         }
135         // Record the activity, get an ID.
136         $item = new \stdClass();
137         $item->categoryid = $course->category;
138         $item->shortname = $course->shortname;
139         $item->fullname = $course->fullname;
140         $item->timecreated = time();
141         $binid = $DB->insert_record('tool_recyclebin_category', $item);
143         // Create the location we want to copy this file to.
144         $filerecord = array(
145             'contextid' => \context_coursecat::instance($course->category)->id,
146             'component' => 'tool_recyclebin',
147             'filearea' => TOOL_RECYCLEBIN_COURSECAT_BIN_FILEAREA,
148             'itemid' => $binid,
149             'timemodified' => time()
150         );
152         // Move the file to our own special little place.
153         $fs = get_file_storage();
154         if (!$fs->create_file_from_storedfile($filerecord, $file)) {
155             // Failed, cleanup first.
156             $DB->delete_records('tool_recyclebin_category', array(
157                 'id' => $binid
158             ));
160             throw new \moodle_exception("Failed to copy backup file to recyclebin.");
161         }
163         // Delete the old file.
164         $file->delete();
166         // Fire event.
167         $event = \tool_recyclebin\event\category_bin_item_created::create(array(
168             'objectid' => $binid,
169             'context' => \context_coursecat::instance($course->category)
170         ));
171         $event->trigger();
172     }
174     /**
175      * Restore an item from the recycle bin.
176      *
177      * @param \stdClass $item The item database record
178      * @throws \moodle_exception
179      */
180     public function restore_item($item) {
181         global $CFG, $OUTPUT, $PAGE;
183         require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
184         require_once($CFG->dirroot . '/course/lib.php');
186         $user = get_admin();
188         // Grab the course category context.
189         $context = \context_coursecat::instance($this->_categoryid);
191         // Get the backup file.
192         $fs = get_file_storage();
193         $files = $fs->get_area_files($context->id, 'tool_recyclebin', TOOL_RECYCLEBIN_COURSECAT_BIN_FILEAREA, $item->id,
194             'itemid, filepath, filename', false);
196         if (empty($files)) {
197             throw new \moodle_exception('Invalid recycle bin item!');
198         }
200         if (count($files) > 1) {
201             throw new \moodle_exception('Too many files found!');
202         }
204         // Get the backup file.
205         $file = reset($files);
207         // Get a temp directory name and create it.
208         $tempdir = \restore_controller::get_tempdir_name($context->id, $user->id);
209         $fulltempdir = make_temp_directory('/backup/' . $tempdir);
211         // Extract the backup to tmpdir.
212         $fb = get_file_packer('application/vnd.moodle.backup');
213         $fb->extract_to_pathname($file, $fulltempdir);
215         // Build a course.
216         $course = new \stdClass();
217         $course->category = $this->_categoryid;
218         $course->shortname = $item->shortname;
219         $course->fullname = $item->fullname;
220         $course->summary = '';
222         // Create a new course.
223         $course = create_course($course);
224         if (!$course) {
225             throw new \moodle_exception("Could not create course to restore into.");
226         }
228         // Define the import.
229         $controller = new \restore_controller(
230             $tempdir,
231             $course->id,
232             \backup::INTERACTIVE_NO,
233             \backup::MODE_GENERAL,
234             $user->id,
235             \backup::TARGET_NEW_COURSE
236         );
238         // Prechecks.
239         if (!$controller->execute_precheck()) {
240             $results = $controller->get_precheck_results();
242             // Check if errors have been found.
243             if (!empty($results['errors'])) {
244                 // Delete the temporary file we created.
245                 fulldelete($fulltempdir);
247                 // Delete the course we created.
248                 delete_course($course, false);
250                 echo $OUTPUT->header();
251                 $backuprenderer = $PAGE->get_renderer('core', 'backup');
252                 echo $backuprenderer->precheck_notices($results);
253                 echo $OUTPUT->continue_button(new \moodle_url('/course/index.php', array('categoryid' => $this->_categoryid)));
254                 echo $OUTPUT->footer();
255                 exit();
256             }
257         }
259         // Run the import.
260         $controller->execute_plan();
262         // Fire event.
263         $event = \tool_recyclebin\event\category_bin_item_restored::create(array(
264             'objectid' => $item->id,
265             'context' => $context
266         ));
267         $event->add_record_snapshot('tool_recyclebin_category', $item);
268         $event->trigger();
270         // Cleanup.
271         fulldelete($fulltempdir);
272         $this->delete_item($item);
273     }
275     /**
276      * Delete an item from the recycle bin.
277      *
278      * @param \stdClass $item The item database record
279      * @throws \coding_exception
280      */
281     public function delete_item($item) {
282         global $DB;
284         // Grab the course category context.
285         $context = \context_coursecat::instance($this->_categoryid);
287         // Delete the files.
288         $fs = get_file_storage();
289         $files = $fs->get_area_files($context->id, 'tool_recyclebin', TOOL_RECYCLEBIN_COURSECAT_BIN_FILEAREA, $item->id);
290         foreach ($files as $file) {
291             $file->delete();
292         }
294         // Delete the record.
295         $DB->delete_records('tool_recyclebin_category', array(
296             'id' => $item->id
297         ));
299         // Fire event.
300         $event = \tool_recyclebin\event\category_bin_item_deleted::create(array(
301             'objectid' => $item->id,
302             'context' => \context_coursecat::instance($item->categoryid)
303         ));
304         $event->add_record_snapshot('tool_recyclebin_category', $item);
305         $event->trigger();
306     }
308     /**
309      * Can we view items in this recycle bin?
310      *
311      * @return bool returns true if they can view, false if not
312      */
313     public function can_view() {
314         $context = \context_coursecat::instance($this->_categoryid);
315         return has_capability('tool/recyclebin:viewitems', $context);
316     }
318     /**
319      * Can we restore items in this recycle bin?
320      *
321      * @return bool returns true if they can restore, false if not
322      */
323     public function can_restore() {
324         $context = \context_coursecat::instance($this->_categoryid);
325         return has_capability('tool/recyclebin:restoreitems', $context);
326     }
328     /**
329      * Can we delete items in this recycle bin?
330      *
331      * @return bool returns true if they can delete, false if not
332      */
333     public function can_delete() {
334         $context = \context_coursecat::instance($this->_categoryid);
335         return has_capability('tool/recyclebin:deleteitems', $context);
336     }